@rollup/wasm-node 4.28.1 → 4.29.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.28.1
4
- Fri, 06 Dec 2024 11:44:27 GMT - commit e60fb1c5d4e54ed5257495215eeda1bb43cf54ba
3
+ Rollup.js v4.29.0-1
4
+ Thu, 19 Dec 2024 06:37:00 GMT - commit fa5064084196636acd98263f95ffea59f8362e32
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.28.1";
34
+ var version = "4.29.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
@@ -3522,71 +3482,6 @@ function renderSystemExportSequenceBeforeExpression(exportedVariable, expression
3522
3482
  }
3523
3483
  }
3524
3484
 
3525
- /** @import { Node } from 'estree' */
3526
-
3527
- /**
3528
- * @param {Node} node
3529
- * @param {Node} parent
3530
- * @returns {boolean}
3531
- */
3532
- function is_reference(node, parent) {
3533
- if (node.type === 'MemberExpression') {
3534
- return !node.computed && is_reference(node.object, node);
3535
- }
3536
-
3537
- if (node.type !== 'Identifier') return false;
3538
-
3539
- switch (parent?.type) {
3540
- // disregard `bar` in `foo.bar`
3541
- case 'MemberExpression':
3542
- return parent.computed || node === parent.object;
3543
-
3544
- // disregard the `foo` in `class {foo(){}}` but keep it in `class {[foo](){}}`
3545
- case 'MethodDefinition':
3546
- return parent.computed;
3547
-
3548
- // disregard the `meta` in `import.meta`
3549
- case 'MetaProperty':
3550
- return parent.meta === node;
3551
-
3552
- // disregard the `foo` in `class {foo=bar}` but keep it in `class {[foo]=bar}` and `class {bar=foo}`
3553
- case 'PropertyDefinition':
3554
- return parent.computed || node === parent.value;
3555
-
3556
- // disregard the `bar` in `{ bar: foo }`, but keep it in `{ [bar]: foo }`
3557
- case 'Property':
3558
- return parent.computed || node === parent.value;
3559
-
3560
- // disregard the `bar` in `export { foo as bar }` or
3561
- // the foo in `import { foo as bar }`
3562
- case 'ExportSpecifier':
3563
- case 'ImportSpecifier':
3564
- return node === parent.local;
3565
-
3566
- // disregard the `foo` in `foo: while (...) { ... break foo; ... continue foo;}`
3567
- case 'LabeledStatement':
3568
- case 'BreakStatement':
3569
- case 'ContinueStatement':
3570
- return false;
3571
-
3572
- default:
3573
- return true;
3574
- }
3575
- }
3576
-
3577
- const PureFunctionKey = Symbol('PureFunction');
3578
- const getPureFunctions = ({ treeshake }) => {
3579
- const pureFunctions = Object.create(null);
3580
- for (const functionName of treeshake ? treeshake.manualPureFunctions : []) {
3581
- let currentFunctions = pureFunctions;
3582
- for (const pathSegment of functionName.split('.')) {
3583
- currentFunctions = currentFunctions[pathSegment] ||= Object.create(null);
3584
- }
3585
- currentFunctions[PureFunctionKey] = true;
3586
- }
3587
- return pureFunctions;
3588
- };
3589
-
3590
3485
  const UnknownKey = Symbol('Unknown Key');
3591
3486
  const UnknownNonAccessorKey = Symbol('Unknown Non-Accessor Key');
3592
3487
  const UnknownInteger = Symbol('Unknown Integer');
@@ -3601,7 +3496,7 @@ const UNKNOWN_PATH = [UnknownKey];
3601
3496
  const UNKNOWN_NON_ACCESSOR_PATH = [UnknownNonAccessorKey];
3602
3497
  const UNKNOWN_INTEGER_PATH = [UnknownInteger];
3603
3498
  const EntitiesKey = Symbol('Entities');
3604
- class PathTracker {
3499
+ class EntityPathTracker {
3605
3500
  constructor() {
3606
3501
  this.entityPaths = Object.create(null, {
3607
3502
  [EntitiesKey]: { value: new Set() }
@@ -3626,14 +3521,14 @@ class PathTracker {
3626
3521
  getEntities(path) {
3627
3522
  let currentPaths = this.entityPaths;
3628
3523
  for (const pathSegment of path) {
3629
- currentPaths = currentPaths[pathSegment] =
3630
- currentPaths[pathSegment] ||
3631
- Object.create(null, { [EntitiesKey]: { value: new Set() } });
3524
+ currentPaths = currentPaths[pathSegment] ||= Object.create(null, {
3525
+ [EntitiesKey]: { value: new Set() }
3526
+ });
3632
3527
  }
3633
3528
  return currentPaths[EntitiesKey];
3634
3529
  }
3635
3530
  }
3636
- const SHARED_RECURSION_TRACKER = new PathTracker();
3531
+ const SHARED_RECURSION_TRACKER = new EntityPathTracker();
3637
3532
  class DiscriminatedPathTracker {
3638
3533
  constructor() {
3639
3534
  this.entityPaths = Object.create(null, {
@@ -3643,9 +3538,9 @@ class DiscriminatedPathTracker {
3643
3538
  trackEntityAtPathAndGetIfTracked(path, discriminator, entity) {
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 Map() } });
3541
+ currentPaths = currentPaths[pathSegment] ||= Object.create(null, {
3542
+ [EntitiesKey]: { value: new Map() }
3543
+ });
3649
3544
  }
3650
3545
  const trackedEntities = getOrCreate(currentPaths[EntitiesKey], discriminator, (getNewSet));
3651
3546
  if (trackedEntities.has(entity))
@@ -3654,6 +3549,137 @@ class DiscriminatedPathTracker {
3654
3549
  return false;
3655
3550
  }
3656
3551
  }
3552
+ const UNKNOWN_INCLUDED_PATH = Object.freeze({ [UnknownKey]: parseAst_js.EMPTY_OBJECT });
3553
+ class IncludedPathTracker {
3554
+ constructor() {
3555
+ this.includedPaths = null;
3556
+ }
3557
+ includePathAndGetIfIncluded(path) {
3558
+ let included = true;
3559
+ let parent = this;
3560
+ let parentSegment = 'includedPaths';
3561
+ let currentPaths = (this.includedPaths ||=
3562
+ ((included = false), Object.create(null)));
3563
+ for (const pathSegment of path) {
3564
+ // This means from here, all paths are included
3565
+ if (currentPaths[UnknownKey]) {
3566
+ return true;
3567
+ }
3568
+ // Including UnknownKey automatically includes all nested paths.
3569
+ // From above, we know that UnknownKey is not included yet.
3570
+ if (typeof pathSegment === 'symbol') {
3571
+ // Hopefully, this saves some memory over just setting
3572
+ // currentPaths[UnknownKey] = EMPTY_OBJECT
3573
+ parent[parentSegment] = UNKNOWN_INCLUDED_PATH;
3574
+ return false;
3575
+ }
3576
+ parent = currentPaths;
3577
+ parentSegment = pathSegment;
3578
+ currentPaths = currentPaths[pathSegment] ||= ((included = false), Object.create(null));
3579
+ }
3580
+ return included;
3581
+ }
3582
+ includeAllPaths(entity, context, basePath) {
3583
+ const { includedPaths } = this;
3584
+ if (includedPaths) {
3585
+ includeAllPaths(entity, context, basePath, includedPaths);
3586
+ }
3587
+ }
3588
+ }
3589
+ function includeAllPaths(entity, context, basePath, currentPaths) {
3590
+ if (currentPaths[UnknownKey]) {
3591
+ return entity.includePath([...basePath, UnknownKey], context);
3592
+ }
3593
+ const keys = Object.keys(currentPaths);
3594
+ if (keys.length === 0) {
3595
+ return entity.includePath(basePath, context);
3596
+ }
3597
+ for (const key of keys) {
3598
+ includeAllPaths(entity, context, [...basePath, key], currentPaths[key]);
3599
+ }
3600
+ }
3601
+
3602
+ /** @import { Node } from 'estree' */
3603
+
3604
+ /**
3605
+ * @param {Node} node
3606
+ * @param {Node} parent
3607
+ * @returns {boolean}
3608
+ */
3609
+ function is_reference(node, parent) {
3610
+ if (node.type === 'MemberExpression') {
3611
+ return !node.computed && is_reference(node.object, node);
3612
+ }
3613
+
3614
+ if (node.type !== 'Identifier') return false;
3615
+
3616
+ switch (parent?.type) {
3617
+ // disregard `bar` in `foo.bar`
3618
+ case 'MemberExpression':
3619
+ return parent.computed || node === parent.object;
3620
+
3621
+ // disregard the `foo` in `class {foo(){}}` but keep it in `class {[foo](){}}`
3622
+ case 'MethodDefinition':
3623
+ return parent.computed;
3624
+
3625
+ // disregard the `meta` in `import.meta`
3626
+ case 'MetaProperty':
3627
+ return parent.meta === node;
3628
+
3629
+ // disregard the `foo` in `class {foo=bar}` but keep it in `class {[foo]=bar}` and `class {bar=foo}`
3630
+ case 'PropertyDefinition':
3631
+ return parent.computed || node === parent.value;
3632
+
3633
+ // disregard the `bar` in `{ bar: foo }`, but keep it in `{ [bar]: foo }`
3634
+ case 'Property':
3635
+ return parent.computed || node === parent.value;
3636
+
3637
+ // disregard the `bar` in `export { foo as bar }` or
3638
+ // the foo in `import { foo as bar }`
3639
+ case 'ExportSpecifier':
3640
+ case 'ImportSpecifier':
3641
+ return node === parent.local;
3642
+
3643
+ // disregard the `foo` in `foo: while (...) { ... break foo; ... continue foo;}`
3644
+ case 'LabeledStatement':
3645
+ case 'BreakStatement':
3646
+ case 'ContinueStatement':
3647
+ return false;
3648
+
3649
+ default:
3650
+ return true;
3651
+ }
3652
+ }
3653
+
3654
+ function createInclusionContext() {
3655
+ return {
3656
+ brokenFlow: false,
3657
+ hasBreak: false,
3658
+ hasContinue: false,
3659
+ includedCallArguments: new Set(),
3660
+ includedLabels: new Set()
3661
+ };
3662
+ }
3663
+ function createHasEffectsContext() {
3664
+ return {
3665
+ accessed: new EntityPathTracker(),
3666
+ assigned: new EntityPathTracker(),
3667
+ brokenFlow: false,
3668
+ called: new DiscriminatedPathTracker(),
3669
+ hasBreak: false,
3670
+ hasContinue: false,
3671
+ ignore: {
3672
+ breaks: false,
3673
+ continues: false,
3674
+ labels: new Set(),
3675
+ returnYield: false,
3676
+ this: false
3677
+ },
3678
+ includedLabels: new Set(),
3679
+ instantiated: new DiscriminatedPathTracker(),
3680
+ replacedVariableInits: new Map()
3681
+ };
3682
+ }
3657
3683
 
3658
3684
  function isFlagSet(flags, flag) {
3659
3685
  return (flags & flag) !== 0;
@@ -3692,12 +3718,25 @@ class ExpressionEntity {
3692
3718
  hasEffectsOnInteractionAtPath(_path, _interaction, _context) {
3693
3719
  return true;
3694
3720
  }
3695
- include(_context, _includeChildrenRecursively, _options) {
3721
+ include(context, _includeChildrenRecursively, _options) {
3722
+ if (!this.included)
3723
+ this.includeNode(context);
3724
+ }
3725
+ includeNode(_context) {
3696
3726
  this.included = true;
3697
3727
  }
3698
- includeCallArguments(context, parameters) {
3699
- for (const argument of parameters) {
3700
- argument.include(context, false);
3728
+ includePath(_path, context) {
3729
+ if (!this.included)
3730
+ this.includeNode(context);
3731
+ }
3732
+ /* We are both including and including an unknown path here as the former
3733
+ * ensures that nested nodes are included while the latter ensures that all
3734
+ * paths of the expression are included.
3735
+ * */
3736
+ includeCallArguments(context, interaction) {
3737
+ for (const argument of interaction.args) {
3738
+ argument?.includePath(UNKNOWN_PATH, context);
3739
+ argument?.include(context, false);
3701
3740
  }
3702
3741
  }
3703
3742
  shouldBeIncluded(_context) {
@@ -3736,6 +3775,19 @@ const NODE_INTERACTION_UNKNOWN_CALL = {
3736
3775
  withNew: false
3737
3776
  };
3738
3777
 
3778
+ const PureFunctionKey = Symbol('PureFunction');
3779
+ const getPureFunctions = ({ treeshake }) => {
3780
+ const pureFunctions = Object.create(null);
3781
+ for (const functionName of treeshake ? treeshake.manualPureFunctions : []) {
3782
+ let currentFunctions = pureFunctions;
3783
+ for (const pathSegment of functionName.split('.')) {
3784
+ currentFunctions = currentFunctions[pathSegment] ||= Object.create(null);
3785
+ }
3786
+ currentFunctions[PureFunctionKey] = true;
3787
+ }
3788
+ return pureFunctions;
3789
+ };
3790
+
3739
3791
  class Variable extends ExpressionEntity {
3740
3792
  markReassigned() {
3741
3793
  this.isReassigned = true;
@@ -3812,9 +3864,9 @@ class Variable extends ExpressionEntity {
3812
3864
  * has not been included previously. Once a variable is included, it should
3813
3865
  * take care all its declarations are included.
3814
3866
  */
3815
- include() {
3867
+ includePath(path, context) {
3816
3868
  this.included = true;
3817
- this.renderedLikeHoisted?.include();
3869
+ this.renderedLikeHoisted?.includePath(path, context);
3818
3870
  }
3819
3871
  /**
3820
3872
  * Links the rendered name of this variable to another variable and includes
@@ -3846,8 +3898,8 @@ class ExternalVariable extends Variable {
3846
3898
  hasEffectsOnInteractionAtPath(path, { type }) {
3847
3899
  return type !== INTERACTION_ACCESSED || path.length > (this.isNamespace ? 1 : 0);
3848
3900
  }
3849
- include() {
3850
- super.include();
3901
+ includePath(path, context) {
3902
+ super.includePath(path, context);
3851
3903
  this.module.used = true;
3852
3904
  }
3853
3905
  }
@@ -4146,36 +4198,6 @@ const childNodeKeys = {
4146
4198
  YieldExpression: ['argument']
4147
4199
  };
4148
4200
 
4149
- function createInclusionContext() {
4150
- return {
4151
- brokenFlow: false,
4152
- hasBreak: false,
4153
- hasContinue: false,
4154
- includedCallArguments: new Set(),
4155
- includedLabels: new Set()
4156
- };
4157
- }
4158
- function createHasEffectsContext() {
4159
- return {
4160
- accessed: new PathTracker(),
4161
- assigned: new PathTracker(),
4162
- brokenFlow: false,
4163
- called: new DiscriminatedPathTracker(),
4164
- hasBreak: false,
4165
- hasContinue: false,
4166
- ignore: {
4167
- breaks: false,
4168
- continues: false,
4169
- labels: new Set(),
4170
- returnYield: false,
4171
- this: false
4172
- },
4173
- includedLabels: new Set(),
4174
- instantiated: new DiscriminatedPathTracker(),
4175
- replacedVariableInits: new Map()
4176
- };
4177
- }
4178
-
4179
4201
  const INCLUDE_PARAMETERS = 'variables';
4180
4202
  const IS_SKIPPED_CHAIN = Symbol('IS_SKIPPED_CHAIN');
4181
4203
  class NodeBase extends ExpressionEntity {
@@ -4245,9 +4267,8 @@ class NodeBase extends ExpressionEntity {
4245
4267
  this.hasEffectsOnInteractionAtPath(EMPTY_PATH, this.assignmentInteraction, context));
4246
4268
  }
4247
4269
  include(context, includeChildrenRecursively, _options) {
4248
- if (!this.deoptimized)
4249
- this.applyDeoptimizations();
4250
- this.included = true;
4270
+ if (!this.included)
4271
+ this.includeNode(context);
4251
4272
  for (const key of childNodeKeys[this.type]) {
4252
4273
  const value = this[key];
4253
4274
  if (value === null)
@@ -4262,6 +4283,24 @@ class NodeBase extends ExpressionEntity {
4262
4283
  }
4263
4284
  }
4264
4285
  }
4286
+ includeNode(context) {
4287
+ this.included = true;
4288
+ if (!this.deoptimized)
4289
+ this.applyDeoptimizations();
4290
+ for (const key of childNodeKeys[this.type]) {
4291
+ const value = this[key];
4292
+ if (value === null)
4293
+ continue;
4294
+ if (Array.isArray(value)) {
4295
+ for (const child of value) {
4296
+ child?.includePath(UNKNOWN_PATH, context);
4297
+ }
4298
+ }
4299
+ else {
4300
+ value.includePath(UNKNOWN_PATH, context);
4301
+ }
4302
+ }
4303
+ }
4265
4304
  includeAsAssignmentTarget(context, includeChildrenRecursively, _deoptimizeAccess) {
4266
4305
  this.include(context, includeChildrenRecursively);
4267
4306
  }
@@ -4365,6 +4404,17 @@ class NodeBase extends ExpressionEntity {
4365
4404
  function createChildNodeKeysForNode(esTreeNode) {
4366
4405
  return Object.keys(esTreeNode).filter(key => typeof esTreeNode[key] === 'object' && key.charCodeAt(0) !== 95 /* _ */);
4367
4406
  }
4407
+ function onlyIncludeSelf() {
4408
+ this.included = true;
4409
+ if (!this.deoptimized)
4410
+ this.applyDeoptimizations();
4411
+ }
4412
+ function onlyIncludeSelfNoDeoptimize() {
4413
+ this.included = true;
4414
+ }
4415
+ function doNotDeoptimize() {
4416
+ this.deoptimized = true;
4417
+ }
4368
4418
 
4369
4419
  function isObjectExpressionNode(node) {
4370
4420
  return node instanceof NodeBase && node.type === parseAst_js.ObjectExpression;
@@ -4377,8 +4427,8 @@ function assembleMemberDescriptions(memberDescriptions, inheritedDescriptions =
4377
4427
  return Object.create(inheritedDescriptions, memberDescriptions);
4378
4428
  }
4379
4429
  const UNDEFINED_EXPRESSION = new (class UndefinedExpression extends ExpressionEntity {
4380
- getLiteralValueAtPath() {
4381
- return undefined;
4430
+ getLiteralValueAtPath(path) {
4431
+ return path.length > 0 ? UnknownValue : undefined;
4382
4432
  }
4383
4433
  })();
4384
4434
  const returnsUnknown = {
@@ -4575,31 +4625,6 @@ function getMemberReturnExpressionWhenCalled(members, memberName) {
4575
4625
  return [members[memberName].returns, false];
4576
4626
  }
4577
4627
 
4578
- class SpreadElement extends NodeBase {
4579
- deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
4580
- if (path.length > 0) {
4581
- this.argument.deoptimizeArgumentsOnInteractionAtPath(interaction, UNKNOWN_PATH, recursionTracker);
4582
- }
4583
- }
4584
- hasEffects(context) {
4585
- if (!this.deoptimized)
4586
- this.applyDeoptimizations();
4587
- const { propertyReadSideEffects } = this.scope.context.options
4588
- .treeshake;
4589
- return (this.argument.hasEffects(context) ||
4590
- (propertyReadSideEffects &&
4591
- (propertyReadSideEffects === 'always' ||
4592
- this.argument.hasEffectsOnInteractionAtPath(UNKNOWN_PATH, NODE_INTERACTION_UNKNOWN_ACCESS, context))));
4593
- }
4594
- applyDeoptimizations() {
4595
- this.deoptimized = true;
4596
- // Only properties of properties of the argument could become subject to reassignment
4597
- // This will also reassign the return values of iterators
4598
- this.argument.deoptimizePath([UnknownKey, UnknownKey]);
4599
- this.scope.context.requestTreeshakingPass();
4600
- }
4601
- }
4602
-
4603
4628
  class Method extends ExpressionEntity {
4604
4629
  constructor(description) {
4605
4630
  super();
@@ -4725,6 +4750,7 @@ class ObjectEntity extends ExpressionEntity {
4725
4750
  this.unknownIntegerProps = [];
4726
4751
  this.unmatchableGetters = [];
4727
4752
  this.unmatchablePropertiesAndGetters = [];
4753
+ this.unmatchablePropertiesAndSetters = [];
4728
4754
  this.unmatchableSetters = [];
4729
4755
  if (Array.isArray(properties)) {
4730
4756
  this.buildPropertyMaps(properties);
@@ -4959,9 +4985,38 @@ class ObjectEntity extends ExpressionEntity {
4959
4985
  }
4960
4986
  return false;
4961
4987
  }
4988
+ include(context, includeChildrenRecursively) {
4989
+ this.included = true;
4990
+ for (const property of this.allProperties) {
4991
+ if (includeChildrenRecursively || property.shouldBeIncluded(context)) {
4992
+ property.include(context, includeChildrenRecursively);
4993
+ }
4994
+ }
4995
+ this.prototypeExpression?.include(context, includeChildrenRecursively);
4996
+ }
4997
+ includePath(path, context) {
4998
+ this.included = true;
4999
+ if (path.length === 0)
5000
+ return;
5001
+ const [key, ...subPath] = path;
5002
+ const [includedMembers, includedPath] = typeof key === 'string'
5003
+ ? [
5004
+ [
5005
+ ...new Set([
5006
+ ...(this.propertiesAndGettersByKey[key] || this.unmatchablePropertiesAndGetters),
5007
+ ...(this.propertiesAndSettersByKey[key] || this.unmatchablePropertiesAndSetters)
5008
+ ])
5009
+ ],
5010
+ subPath
5011
+ ]
5012
+ : [this.allProperties, UNKNOWN_PATH];
5013
+ for (const property of includedMembers) {
5014
+ property.includePath(includedPath, context);
5015
+ }
5016
+ this.prototypeExpression?.includePath(path, context);
5017
+ }
4962
5018
  buildPropertyMaps(properties) {
4963
- const { allProperties, propertiesAndGettersByKey, propertiesAndSettersByKey, settersByKey, gettersByKey, unknownIntegerProps, unmatchablePropertiesAndGetters, unmatchableGetters, unmatchableSetters } = this;
4964
- const unmatchablePropertiesAndSetters = [];
5019
+ const { allProperties, propertiesAndGettersByKey, propertiesAndSettersByKey, settersByKey, gettersByKey, unknownIntegerProps, unmatchablePropertiesAndGetters, unmatchablePropertiesAndSetters, unmatchableGetters, unmatchableSetters } = this;
4965
5020
  for (let index = properties.length - 1; index >= 0; index--) {
4966
5021
  const { key, kind, property } = properties[index];
4967
5022
  allProperties.push(property);
@@ -5231,6 +5286,37 @@ const ARRAY_PROTOTYPE = new ObjectEntity({
5231
5286
  values: METHOD_DEOPTS_SELF_RETURNS_UNKNOWN
5232
5287
  }, OBJECT_PROTOTYPE, true);
5233
5288
 
5289
+ class SpreadElement extends NodeBase {
5290
+ deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
5291
+ if (path.length > 0) {
5292
+ this.argument.deoptimizeArgumentsOnInteractionAtPath(interaction, UNKNOWN_PATH, recursionTracker);
5293
+ }
5294
+ }
5295
+ hasEffects(context) {
5296
+ if (!this.deoptimized)
5297
+ this.applyDeoptimizations();
5298
+ const { propertyReadSideEffects } = this.scope.context.options
5299
+ .treeshake;
5300
+ return (this.argument.hasEffects(context) ||
5301
+ (propertyReadSideEffects &&
5302
+ (propertyReadSideEffects === 'always' ||
5303
+ this.argument.hasEffectsOnInteractionAtPath(UNKNOWN_PATH, NODE_INTERACTION_UNKNOWN_ACCESS, context))));
5304
+ }
5305
+ includeNode(context) {
5306
+ this.included = true;
5307
+ if (!this.deoptimized)
5308
+ this.applyDeoptimizations();
5309
+ this.argument.includePath(UNKNOWN_PATH, context);
5310
+ }
5311
+ applyDeoptimizations() {
5312
+ this.deoptimized = true;
5313
+ // Only properties of properties of the argument could become subject to reassignment
5314
+ // This will also reassign the return values of iterators
5315
+ this.argument.deoptimizePath([UnknownKey, UnknownKey]);
5316
+ this.scope.context.requestTreeshakingPass();
5317
+ }
5318
+ }
5319
+
5234
5320
  class ArrayExpression extends NodeBase {
5235
5321
  constructor() {
5236
5322
  super(...arguments);
@@ -5251,6 +5337,16 @@ class ArrayExpression extends NodeBase {
5251
5337
  hasEffectsOnInteractionAtPath(path, interaction, context) {
5252
5338
  return this.getObjectEntity().hasEffectsOnInteractionAtPath(path, interaction, context);
5253
5339
  }
5340
+ includeNode(context) {
5341
+ this.included = true;
5342
+ if (!this.deoptimized)
5343
+ this.applyDeoptimizations();
5344
+ for (const element of this.elements) {
5345
+ if (element) {
5346
+ element?.includePath(UNKNOWN_PATH, context);
5347
+ }
5348
+ }
5349
+ }
5254
5350
  applyDeoptimizations() {
5255
5351
  this.deoptimized = true;
5256
5352
  let hasSpread = false;
@@ -6318,17 +6414,37 @@ class GlobalVariable extends Variable {
6318
6414
  }
6319
6415
  }
6320
6416
 
6417
+ // To avoid infinite recursions
6418
+ const MAX_PATH_DEPTH = 6;
6419
+ // If a path is longer than MAX_PATH_DEPTH, it is truncated so that it is at
6420
+ // most MAX_PATH_DEPTH long. The last element is always UnknownKey
6421
+ const limitConcatenatedPathDepth = (path1, path2) => {
6422
+ const { length: length1 } = path1;
6423
+ const { length: length2 } = path2;
6424
+ return length1 === 0
6425
+ ? path2
6426
+ : length2 === 0
6427
+ ? path1
6428
+ : length1 + length2 > MAX_PATH_DEPTH
6429
+ ? [...path1, ...path2.slice(0, MAX_PATH_DEPTH - 1 - path1.length), 'UnknownKey']
6430
+ : [...path1, ...path2];
6431
+ };
6432
+
6321
6433
  class LocalVariable extends Variable {
6322
- constructor(name, declarator, init, context, kind) {
6434
+ constructor(name, declarator, init,
6435
+ /** if this is non-empty, the actual init is this path of this.init */
6436
+ initPath, context, kind) {
6323
6437
  super(name);
6324
6438
  this.init = init;
6439
+ this.initPath = initPath;
6440
+ this.kind = kind;
6325
6441
  this.calledFromTryStatement = false;
6326
6442
  this.additionalInitializers = null;
6443
+ this.includedPathTracker = new IncludedPathTracker();
6327
6444
  this.expressionsToBeDeoptimized = [];
6328
6445
  this.declarations = declarator ? [declarator] : [];
6329
6446
  this.deoptimizationTracker = context.deoptimizationTracker;
6330
6447
  this.module = context.module;
6331
- this.kind = kind;
6332
6448
  }
6333
6449
  addDeclaration(identifier, init) {
6334
6450
  this.declarations.push(identifier);
@@ -6339,15 +6455,16 @@ class LocalVariable extends Variable {
6339
6455
  for (const initializer of this.additionalInitializers) {
6340
6456
  initializer.deoptimizePath(UNKNOWN_PATH);
6341
6457
  }
6342
- this.additionalInitializers = null;
6343
6458
  }
6344
6459
  }
6345
6460
  deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
6346
- if (this.isReassigned) {
6461
+ if (this.isReassigned || path.length + this.initPath.length > MAX_PATH_DEPTH) {
6347
6462
  deoptimizeInteraction(interaction);
6348
6463
  return;
6349
6464
  }
6350
- recursionTracker.withTrackedEntityAtPath(path, this.init, () => this.init.deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker), undefined);
6465
+ recursionTracker.withTrackedEntityAtPath(path, this.init, () => {
6466
+ this.init.deoptimizeArgumentsOnInteractionAtPath(interaction, [...this.initPath, ...path], recursionTracker);
6467
+ }, undefined);
6351
6468
  }
6352
6469
  deoptimizePath(path) {
6353
6470
  if (this.isReassigned ||
@@ -6361,37 +6478,40 @@ class LocalVariable extends Variable {
6361
6478
  for (const expression of expressionsToBeDeoptimized) {
6362
6479
  expression.deoptimizeCache();
6363
6480
  }
6364
- this.init.deoptimizePath(UNKNOWN_PATH);
6481
+ this.init.deoptimizePath([...this.initPath, UnknownKey]);
6365
6482
  }
6366
6483
  else {
6367
- this.init.deoptimizePath(path);
6484
+ this.init.deoptimizePath(limitConcatenatedPathDepth(this.initPath, path));
6368
6485
  }
6369
6486
  }
6370
6487
  getLiteralValueAtPath(path, recursionTracker, origin) {
6371
- if (this.isReassigned) {
6488
+ if (this.isReassigned || path.length + this.initPath.length > MAX_PATH_DEPTH) {
6372
6489
  return UnknownValue;
6373
6490
  }
6374
6491
  return recursionTracker.withTrackedEntityAtPath(path, this.init, () => {
6375
6492
  this.expressionsToBeDeoptimized.push(origin);
6376
- return this.init.getLiteralValueAtPath(path, recursionTracker, origin);
6493
+ return this.init.getLiteralValueAtPath([...this.initPath, ...path], recursionTracker, origin);
6377
6494
  }, UnknownValue);
6378
6495
  }
6379
6496
  getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin) {
6380
- if (this.isReassigned) {
6497
+ if (this.isReassigned || path.length + this.initPath.length > MAX_PATH_DEPTH) {
6381
6498
  return UNKNOWN_RETURN_EXPRESSION;
6382
6499
  }
6383
6500
  return recursionTracker.withTrackedEntityAtPath(path, this.init, () => {
6384
6501
  this.expressionsToBeDeoptimized.push(origin);
6385
- return this.init.getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin);
6502
+ return this.init.getReturnExpressionWhenCalledAtPath([...this.initPath, ...path], interaction, recursionTracker, origin);
6386
6503
  }, UNKNOWN_RETURN_EXPRESSION);
6387
6504
  }
6388
6505
  hasEffectsOnInteractionAtPath(path, interaction, context) {
6506
+ if (path.length + this.initPath.length > MAX_PATH_DEPTH) {
6507
+ return true;
6508
+ }
6389
6509
  switch (interaction.type) {
6390
6510
  case INTERACTION_ACCESSED: {
6391
6511
  if (this.isReassigned)
6392
6512
  return true;
6393
6513
  return (!context.accessed.trackEntityAtPathAndGetIfTracked(path, this) &&
6394
- this.init.hasEffectsOnInteractionAtPath(path, interaction, context));
6514
+ this.init.hasEffectsOnInteractionAtPath([...this.initPath, ...path], interaction, context));
6395
6515
  }
6396
6516
  case INTERACTION_ASSIGNED: {
6397
6517
  if (this.included)
@@ -6401,44 +6521,63 @@ class LocalVariable extends Variable {
6401
6521
  if (this.isReassigned)
6402
6522
  return true;
6403
6523
  return (!context.assigned.trackEntityAtPathAndGetIfTracked(path, this) &&
6404
- this.init.hasEffectsOnInteractionAtPath(path, interaction, context));
6524
+ this.init.hasEffectsOnInteractionAtPath([...this.initPath, ...path], interaction, context));
6405
6525
  }
6406
6526
  case INTERACTION_CALLED: {
6407
6527
  if (this.isReassigned)
6408
6528
  return true;
6409
6529
  return (!(interaction.withNew ? context.instantiated : context.called).trackEntityAtPathAndGetIfTracked(path, interaction.args, this) &&
6410
- this.init.hasEffectsOnInteractionAtPath(path, interaction, context));
6530
+ this.init.hasEffectsOnInteractionAtPath([...this.initPath, ...path], interaction, context));
6411
6531
  }
6412
6532
  }
6413
6533
  }
6414
- include() {
6415
- if (!this.included) {
6416
- super.include();
6534
+ includePath(path, context) {
6535
+ if (!this.includedPathTracker.includePathAndGetIfIncluded(path)) {
6536
+ this.module.scope.context.requestTreeshakingPass();
6537
+ if (!this.included) {
6538
+ // This will reduce the number of tree-shaking passes by eagerly
6539
+ // including inits. By pushing this here instead of directly including
6540
+ // we avoid deep call stacks.
6541
+ this.module.scope.context.newlyIncludedVariableInits.add(this.init);
6542
+ }
6543
+ super.includePath(path, context);
6417
6544
  for (const declaration of this.declarations) {
6418
6545
  // If node is a default export, it can save a tree-shaking run to include the full declaration now
6419
6546
  if (!declaration.included)
6420
- declaration.include(createInclusionContext(), false);
6547
+ declaration.include(context, false);
6421
6548
  let node = declaration.parent;
6422
6549
  while (!node.included) {
6423
6550
  // We do not want to properly include parents in case they are part of a dead branch
6424
6551
  // in which case .include() might pull in more dead code
6425
- node.included = true;
6552
+ node.includeNode(context);
6426
6553
  if (node.type === parseAst_js.Program)
6427
6554
  break;
6428
6555
  node = node.parent;
6429
6556
  }
6430
6557
  }
6558
+ // We need to make sure we include the correct path of the init
6559
+ if (path.length > 0) {
6560
+ this.init.includePath(limitConcatenatedPathDepth(this.initPath, path), context);
6561
+ this.additionalInitializers?.forEach(initializer => initializer.includePath(UNKNOWN_PATH, context));
6562
+ }
6431
6563
  }
6432
6564
  }
6433
- includeCallArguments(context, parameters) {
6434
- if (this.isReassigned || context.includedCallArguments.has(this.init)) {
6435
- for (const argument of parameters) {
6436
- argument.include(context, false);
6565
+ includeCallArguments(context, interaction) {
6566
+ if (this.isReassigned ||
6567
+ context.includedCallArguments.has(this.init) ||
6568
+ // This can be removed again once we can include arguments when called at
6569
+ // a specific path
6570
+ this.initPath.length > 0) {
6571
+ for (const argument of interaction.args) {
6572
+ if (argument) {
6573
+ argument.includePath(UNKNOWN_PATH, context);
6574
+ argument.include(context, false);
6575
+ }
6437
6576
  }
6438
6577
  }
6439
6578
  else {
6440
6579
  context.includedCallArguments.add(this.init);
6441
- this.init.includeCallArguments(context, parameters);
6580
+ this.init.includeCallArguments(context, interaction);
6442
6581
  context.includedCallArguments.delete(this.init);
6443
6582
  }
6444
6583
  }
@@ -6518,18 +6657,31 @@ class IdentifierBase extends NodeBase {
6518
6657
  }
6519
6658
  }
6520
6659
  }
6521
- include() {
6660
+ include(context) {
6661
+ if (!this.included)
6662
+ this.includeNode(context);
6663
+ }
6664
+ includeNode(context) {
6665
+ this.included = true;
6522
6666
  if (!this.deoptimized)
6523
6667
  this.applyDeoptimizations();
6668
+ if (this.variable !== null) {
6669
+ this.scope.context.includeVariableInModule(this.variable, EMPTY_PATH, context);
6670
+ }
6671
+ }
6672
+ includePath(path, context) {
6524
6673
  if (!this.included) {
6525
6674
  this.included = true;
6526
6675
  if (this.variable !== null) {
6527
- this.scope.context.includeVariableInModule(this.variable);
6676
+ this.scope.context.includeVariableInModule(this.variable, path, context);
6528
6677
  }
6529
6678
  }
6679
+ else if (path.length > 0) {
6680
+ this.variable?.includePath(path, context);
6681
+ }
6530
6682
  }
6531
- includeCallArguments(context, parameters) {
6532
- this.variable.includeCallArguments(context, parameters);
6683
+ includeCallArguments(context, interaction) {
6684
+ this.variable.includeCallArguments(context, interaction);
6533
6685
  }
6534
6686
  isPossibleTDZ() {
6535
6687
  // return cached value to avoid issues with the next tree-shaking pass
@@ -6603,13 +6755,36 @@ class IdentifierBase extends NodeBase {
6603
6755
  }
6604
6756
  return currentPureFunction?.[PureFunctionKey];
6605
6757
  }
6606
- }
6607
- function closestParentFunctionOrProgram(node) {
6608
- while (node && !/^Program|Function/.test(node.type)) {
6609
- node = node.parent;
6758
+ }
6759
+ function closestParentFunctionOrProgram(node) {
6760
+ while (node && !/^Program|Function/.test(node.type)) {
6761
+ node = node.parent;
6762
+ }
6763
+ // one of: ArrowFunctionExpression, FunctionDeclaration, FunctionExpression or Program
6764
+ return node;
6765
+ }
6766
+
6767
+ class ObjectMember extends ExpressionEntity {
6768
+ constructor(object, path) {
6769
+ super();
6770
+ this.object = object;
6771
+ this.path = path;
6772
+ }
6773
+ deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
6774
+ this.object.deoptimizeArgumentsOnInteractionAtPath(interaction, [...this.path, ...path], recursionTracker);
6775
+ }
6776
+ deoptimizePath(path) {
6777
+ this.object.deoptimizePath([...this.path, ...path]);
6778
+ }
6779
+ getLiteralValueAtPath(path, recursionTracker, origin) {
6780
+ return this.object.getLiteralValueAtPath([...this.path, ...path], recursionTracker, origin);
6781
+ }
6782
+ getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin) {
6783
+ return this.object.getReturnExpressionWhenCalledAtPath([...this.path, ...path], interaction, recursionTracker, origin);
6784
+ }
6785
+ hasEffectsOnInteractionAtPath(path, interaction, context) {
6786
+ return this.object.hasEffectsOnInteractionAtPath([...this.path, ...path], interaction, context);
6610
6787
  }
6611
- // one of: ArrowFunctionExpression, FunctionDeclaration, FunctionExpression or Program
6612
- return node;
6613
6788
  }
6614
6789
 
6615
6790
  class Identifier extends IdentifierBase {
@@ -6617,6 +6792,12 @@ class Identifier extends IdentifierBase {
6617
6792
  super(...arguments);
6618
6793
  this.variable = null;
6619
6794
  }
6795
+ get isDestructuringDeoptimized() {
6796
+ return isFlagSet(this.flags, 8388608 /* Flag.destructuringDeoptimized */);
6797
+ }
6798
+ set isDestructuringDeoptimized(value) {
6799
+ this.flags = setFlag(this.flags, 8388608 /* Flag.destructuringDeoptimized */, value);
6800
+ }
6620
6801
  addExportedVariables(variables, exportNamesByVariable) {
6621
6802
  if (exportNamesByVariable.has(this.variable)) {
6622
6803
  variables.push(this.variable);
@@ -6629,43 +6810,53 @@ class Identifier extends IdentifierBase {
6629
6810
  this.isVariableReference = true;
6630
6811
  }
6631
6812
  }
6632
- declare(kind, init) {
6813
+ declare(kind, destructuredInitPath, init) {
6633
6814
  let variable;
6634
6815
  const { treeshake } = this.scope.context.options;
6635
- switch (kind) {
6636
- case 'var': {
6637
- variable = this.scope.addDeclaration(this, this.scope.context, init, kind);
6638
- if (treeshake && treeshake.correctVarValueBeforeDeclaration) {
6639
- // Necessary to make sure the init is deoptimized. We cannot call deoptimizePath here.
6640
- variable.markInitializersForDeoptimization();
6641
- }
6642
- break;
6643
- }
6644
- case 'function': {
6645
- // in strict mode, functions are only hoisted within a scope but not across block scopes
6646
- variable = this.scope.addDeclaration(this, this.scope.context, init, kind);
6647
- break;
6648
- }
6649
- case 'let':
6650
- case 'const':
6651
- case 'using':
6652
- case 'await using':
6653
- case 'class': {
6654
- variable = this.scope.addDeclaration(this, this.scope.context, init, kind);
6655
- break;
6656
- }
6657
- case 'parameter': {
6658
- variable = this.scope.addParameterDeclaration(this);
6659
- break;
6660
- }
6661
- /* istanbul ignore next */
6662
- default: {
6663
- /* istanbul ignore next */
6664
- throw new Error(`Internal Error: Unexpected identifier kind ${kind}.`);
6816
+ if (kind === 'parameter') {
6817
+ variable = this.scope.addParameterDeclaration(this, destructuredInitPath);
6818
+ }
6819
+ else {
6820
+ variable = this.scope.addDeclaration(this, this.scope.context, init, destructuredInitPath, kind);
6821
+ if (kind === 'var' && treeshake && treeshake.correctVarValueBeforeDeclaration) {
6822
+ // Necessary to make sure the init is deoptimized. We cannot call deoptimizePath here.
6823
+ variable.markInitializersForDeoptimization();
6665
6824
  }
6666
6825
  }
6667
6826
  return [(this.variable = variable)];
6668
6827
  }
6828
+ deoptimizeAssignment(destructuredInitPath, init) {
6829
+ this.deoptimizePath(EMPTY_PATH);
6830
+ init.deoptimizePath([...destructuredInitPath, UnknownKey]);
6831
+ }
6832
+ hasEffectsWhenDestructuring(context, destructuredInitPath, init) {
6833
+ return (destructuredInitPath.length > 0 &&
6834
+ init.hasEffectsOnInteractionAtPath(destructuredInitPath, NODE_INTERACTION_UNKNOWN_ACCESS, context));
6835
+ }
6836
+ includeDestructuredIfNecessary(context, destructuredInitPath, init) {
6837
+ if (destructuredInitPath.length > 0 && !this.isDestructuringDeoptimized) {
6838
+ this.isDestructuringDeoptimized = true;
6839
+ init.deoptimizeArgumentsOnInteractionAtPath({
6840
+ args: [new ObjectMember(init, destructuredInitPath.slice(0, -1))],
6841
+ type: INTERACTION_ACCESSED
6842
+ }, destructuredInitPath, SHARED_RECURSION_TRACKER);
6843
+ }
6844
+ const { propertyReadSideEffects } = this.scope.context.options
6845
+ .treeshake;
6846
+ if ((this.included ||=
6847
+ destructuredInitPath.length > 0 &&
6848
+ !context.brokenFlow &&
6849
+ propertyReadSideEffects &&
6850
+ (propertyReadSideEffects === 'always' ||
6851
+ init.hasEffectsOnInteractionAtPath(destructuredInitPath, NODE_INTERACTION_UNKNOWN_ACCESS, createHasEffectsContext())))) {
6852
+ if (this.variable && !this.variable.included) {
6853
+ this.scope.context.includeVariableInModule(this.variable, EMPTY_PATH, context);
6854
+ }
6855
+ init.includePath(destructuredInitPath, context);
6856
+ return true;
6857
+ }
6858
+ return false;
6859
+ }
6669
6860
  markDeclarationReached() {
6670
6861
  this.variable.initReached = true;
6671
6862
  }
@@ -6718,18 +6909,17 @@ class Scope {
6718
6909
  - then the variable is still declared in the hoisted outer scope, but the initializer is assigned to the parameter
6719
6910
  - const, let, class, and function except in the cases above cannot redeclare anything
6720
6911
  */
6721
- addDeclaration(identifier, context, init, kind) {
6912
+ addDeclaration(identifier, context, init, destructuredInitPath, kind) {
6722
6913
  const name = identifier.name;
6723
6914
  const existingVariable = this.hoistedVariables?.get(name) || this.variables.get(name);
6724
6915
  if (existingVariable) {
6725
- const existingKind = existingVariable.kind;
6726
- if (kind === 'var' && existingKind === 'var') {
6916
+ if (kind === 'var' && existingVariable.kind === 'var') {
6727
6917
  existingVariable.addDeclaration(identifier, init);
6728
6918
  return existingVariable;
6729
6919
  }
6730
6920
  context.error(parseAst_js.logRedeclarationError(name), identifier.start);
6731
6921
  }
6732
- const newVariable = new LocalVariable(identifier.name, identifier, init, context, kind);
6922
+ const newVariable = new LocalVariable(identifier.name, identifier, init, destructuredInitPath, context, kind);
6733
6923
  this.variables.set(name, newVariable);
6734
6924
  return newVariable;
6735
6925
  }
@@ -6905,7 +7095,6 @@ class MethodBase extends NodeBase {
6905
7095
  }
6906
7096
  return this.getAccessedValue()[0].hasEffectsOnInteractionAtPath(path, interaction, context);
6907
7097
  }
6908
- applyDeoptimizations() { }
6909
7098
  getAccessedValue() {
6910
7099
  if (this.accessedValue === null) {
6911
7100
  if (this.kind === 'get') {
@@ -6919,19 +7108,20 @@ class MethodBase extends NodeBase {
6919
7108
  return this.accessedValue;
6920
7109
  }
6921
7110
  }
7111
+ MethodBase.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
7112
+ MethodBase.prototype.applyDeoptimizations = doNotDeoptimize;
6922
7113
 
6923
7114
  class MethodDefinition extends MethodBase {
6924
7115
  hasEffects(context) {
6925
7116
  return super.hasEffects(context) || checkEffectForNodes(this.decorators, context);
6926
7117
  }
6927
- applyDeoptimizations() { }
6928
7118
  }
6929
7119
 
6930
7120
  class BlockScope extends ChildScope {
6931
7121
  constructor(parent) {
6932
7122
  super(parent, parent.context);
6933
7123
  }
6934
- addDeclaration(identifier, context, init, kind) {
7124
+ addDeclaration(identifier, context, init, destructuredInitPath, kind) {
6935
7125
  if (kind === 'var') {
6936
7126
  const name = identifier.name;
6937
7127
  const existingVariable = this.hoistedVariables?.get(name) || this.variables.get(name);
@@ -6943,7 +7133,7 @@ class BlockScope extends ChildScope {
6943
7133
  }
6944
7134
  return context.error(parseAst_js.logRedeclarationError(name), identifier.start);
6945
7135
  }
6946
- const declaredVariable = this.parent.addDeclaration(identifier, context, init, kind);
7136
+ const declaredVariable = this.parent.addDeclaration(identifier, context, init, destructuredInitPath, kind);
6947
7137
  // Necessary to make sure the init is deoptimized for conditional declarations.
6948
7138
  // We cannot call deoptimizePath here.
6949
7139
  declaredVariable.markInitializersForDeoptimization();
@@ -6951,7 +7141,7 @@ class BlockScope extends ChildScope {
6951
7141
  this.addHoistedVariable(name, declaredVariable);
6952
7142
  return declaredVariable;
6953
7143
  }
6954
- return super.addDeclaration(identifier, context, init, kind);
7144
+ return super.addDeclaration(identifier, context, init, destructuredInitPath, kind);
6955
7145
  }
6956
7146
  }
6957
7147
 
@@ -6983,33 +7173,12 @@ class StaticBlock extends NodeBase {
6983
7173
  }
6984
7174
  }
6985
7175
  }
7176
+ StaticBlock.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
7177
+ StaticBlock.prototype.applyDeoptimizations = doNotDeoptimize;
6986
7178
  function isStaticBlock(statement) {
6987
7179
  return statement.type === parseAst_js.StaticBlock;
6988
7180
  }
6989
7181
 
6990
- class ObjectMember extends ExpressionEntity {
6991
- constructor(object, key) {
6992
- super();
6993
- this.object = object;
6994
- this.key = key;
6995
- }
6996
- deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
6997
- this.object.deoptimizeArgumentsOnInteractionAtPath(interaction, [this.key, ...path], recursionTracker);
6998
- }
6999
- deoptimizePath(path) {
7000
- this.object.deoptimizePath([this.key, ...path]);
7001
- }
7002
- getLiteralValueAtPath(path, recursionTracker, origin) {
7003
- return this.object.getLiteralValueAtPath([this.key, ...path], recursionTracker, origin);
7004
- }
7005
- getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin) {
7006
- return this.object.getReturnExpressionWhenCalledAtPath([this.key, ...path], interaction, recursionTracker, origin);
7007
- }
7008
- hasEffectsOnInteractionAtPath(path, interaction, context) {
7009
- return this.object.hasEffectsOnInteractionAtPath([this.key, ...path], interaction, context);
7010
- }
7011
- }
7012
-
7013
7182
  class ClassNode extends NodeBase {
7014
7183
  constructor() {
7015
7184
  super(...arguments);
@@ -7050,21 +7219,20 @@ class ClassNode extends NodeBase {
7050
7219
  : this.getObjectEntity().hasEffectsOnInteractionAtPath(path, interaction, context);
7051
7220
  }
7052
7221
  include(context, includeChildrenRecursively) {
7053
- if (!this.deoptimized)
7054
- this.applyDeoptimizations();
7055
- this.included = true;
7222
+ if (!this.included)
7223
+ this.includeNode(context);
7056
7224
  this.superClass?.include(context, includeChildrenRecursively);
7057
7225
  this.body.include(context, includeChildrenRecursively);
7058
7226
  for (const decorator of this.decorators)
7059
7227
  decorator.include(context, includeChildrenRecursively);
7060
7228
  if (this.id) {
7061
7229
  this.id.markDeclarationReached();
7062
- this.id.include();
7230
+ this.id.include(context);
7063
7231
  }
7064
7232
  }
7065
7233
  initialise() {
7066
7234
  super.initialise();
7067
- this.id?.declare('class', this);
7235
+ this.id?.declare('class', EMPTY_PATH, this);
7068
7236
  for (const method of this.body.body) {
7069
7237
  if (method instanceof MethodDefinition && method.kind === 'constructor') {
7070
7238
  this.classConstructor = method;
@@ -7122,11 +7290,12 @@ class ClassNode extends NodeBase {
7122
7290
  staticProperties.unshift({
7123
7291
  key: 'prototype',
7124
7292
  kind: 'init',
7125
- property: new ObjectEntity(dynamicMethods, this.superClass ? new ObjectMember(this.superClass, 'prototype') : OBJECT_PROTOTYPE)
7293
+ property: new ObjectEntity(dynamicMethods, this.superClass ? new ObjectMember(this.superClass, ['prototype']) : OBJECT_PROTOTYPE)
7126
7294
  });
7127
7295
  return (this.objectEntity = new ObjectEntity(staticProperties, this.superClass || OBJECT_PROTOTYPE));
7128
7296
  }
7129
7297
  }
7298
+ ClassNode.prototype.includeNode = onlyIncludeSelf;
7130
7299
 
7131
7300
  class ClassDeclaration extends ClassNode {
7132
7301
  initialise() {
@@ -7179,7 +7348,7 @@ class ClassDeclaration extends ClassNode {
7179
7348
 
7180
7349
  class ArgumentsVariable extends LocalVariable {
7181
7350
  constructor(context) {
7182
- super('arguments', null, UNKNOWN_EXPRESSION, context, 'other');
7351
+ super('arguments', null, UNKNOWN_EXPRESSION, EMPTY_PATH, context, 'other');
7183
7352
  this.deoptimizedArguments = [];
7184
7353
  }
7185
7354
  addArgumentToBeDeoptimized(argument) {
@@ -7193,8 +7362,8 @@ class ArgumentsVariable extends LocalVariable {
7193
7362
  hasEffectsOnInteractionAtPath(path, { type }) {
7194
7363
  return type !== INTERACTION_ACCESSED || path.length > 1;
7195
7364
  }
7196
- include() {
7197
- super.include();
7365
+ includePath(path, context) {
7366
+ super.includePath(path, context);
7198
7367
  for (const argument of this.deoptimizedArguments) {
7199
7368
  argument.deoptimizePath(UNKNOWN_PATH);
7200
7369
  }
@@ -7205,27 +7374,28 @@ class ArgumentsVariable extends LocalVariable {
7205
7374
  const MAX_TRACKED_INTERACTIONS = 20;
7206
7375
  const NO_INTERACTIONS = parseAst_js.EMPTY_ARRAY;
7207
7376
  const UNKNOWN_DEOPTIMIZED_FIELD = new Set([UnknownKey]);
7208
- const EMPTY_PATH_TRACKER = new PathTracker();
7377
+ const EMPTY_PATH_TRACKER = new EntityPathTracker();
7209
7378
  const UNKNOWN_DEOPTIMIZED_ENTITY = new Set([UNKNOWN_EXPRESSION]);
7210
7379
  class ParameterVariable extends LocalVariable {
7211
- constructor(name, declarator, context) {
7212
- super(name, declarator, UNKNOWN_EXPRESSION, context, 'parameter');
7380
+ constructor(name, declarator, argumentPath, context) {
7381
+ super(name, declarator, UNKNOWN_EXPRESSION, argumentPath, context, 'parameter');
7213
7382
  this.deoptimizationInteractions = [];
7214
- this.deoptimizations = new PathTracker();
7383
+ this.deoptimizations = new EntityPathTracker();
7215
7384
  this.deoptimizedFields = new Set();
7216
- this.entitiesToBeDeoptimized = new Set();
7217
- this.expressionsUseTheKnownValue = [];
7385
+ this.argumentsToBeDeoptimized = new Set();
7386
+ this.expressionsDependingOnKnownValue = [];
7218
7387
  this.knownValue = null;
7219
7388
  this.knownValueLiteral = UnknownValue;
7220
7389
  this.frozenValue = null;
7221
7390
  }
7222
- addEntityToBeDeoptimized(entity) {
7391
+ addArgumentValue(entity) {
7392
+ this.updateKnownValue(entity);
7223
7393
  if (entity === UNKNOWN_EXPRESSION) {
7224
7394
  // As unknown expressions fully deoptimize all interactions, we can clear
7225
7395
  // the interaction cache at this point provided we keep this optimization
7226
7396
  // in mind when adding new interactions
7227
- if (!this.entitiesToBeDeoptimized.has(UNKNOWN_EXPRESSION)) {
7228
- this.entitiesToBeDeoptimized.add(UNKNOWN_EXPRESSION);
7397
+ if (!this.argumentsToBeDeoptimized.has(UNKNOWN_EXPRESSION)) {
7398
+ this.argumentsToBeDeoptimized.add(UNKNOWN_EXPRESSION);
7229
7399
  for (const { interaction } of this.deoptimizationInteractions) {
7230
7400
  deoptimizeInteraction(interaction);
7231
7401
  }
@@ -7235,27 +7405,34 @@ class ParameterVariable extends LocalVariable {
7235
7405
  else if (this.deoptimizedFields.has(UnknownKey)) {
7236
7406
  // This means that we already deoptimized all interactions and no longer
7237
7407
  // track them
7238
- entity.deoptimizePath(UNKNOWN_PATH);
7408
+ entity.deoptimizePath([...this.initPath, UnknownKey]);
7239
7409
  }
7240
- else if (!this.entitiesToBeDeoptimized.has(entity)) {
7241
- this.entitiesToBeDeoptimized.add(entity);
7410
+ else if (!this.argumentsToBeDeoptimized.has(entity)) {
7411
+ this.argumentsToBeDeoptimized.add(entity);
7242
7412
  for (const field of this.deoptimizedFields) {
7243
- entity.deoptimizePath([field]);
7413
+ entity.deoptimizePath([...this.initPath, field]);
7244
7414
  }
7245
7415
  for (const { interaction, path } of this.deoptimizationInteractions) {
7246
- entity.deoptimizeArgumentsOnInteractionAtPath(interaction, path, SHARED_RECURSION_TRACKER);
7416
+ if (this.initPath.length + path.length > MAX_PATH_DEPTH) {
7417
+ deoptimizeInteraction(interaction);
7418
+ continue;
7419
+ }
7420
+ entity.deoptimizeArgumentsOnInteractionAtPath(interaction, [...this.initPath, ...path], SHARED_RECURSION_TRACKER);
7247
7421
  }
7248
7422
  }
7249
7423
  }
7424
+ /** This says we should not make assumptions about the value of the parameter.
7425
+ * This is different from deoptimization that will also cause argument values
7426
+ * to be deoptimized. */
7250
7427
  markReassigned() {
7251
7428
  if (this.isReassigned) {
7252
7429
  return;
7253
7430
  }
7254
7431
  super.markReassigned();
7255
- for (const expression of this.expressionsUseTheKnownValue) {
7432
+ for (const expression of this.expressionsDependingOnKnownValue) {
7256
7433
  expression.deoptimizeCache();
7257
7434
  }
7258
- this.expressionsUseTheKnownValue = parseAst_js.EMPTY_ARRAY;
7435
+ this.expressionsDependingOnKnownValue = parseAst_js.EMPTY_ARRAY;
7259
7436
  }
7260
7437
  deoptimizeCache() {
7261
7438
  this.markReassigned();
@@ -7272,7 +7449,7 @@ class ParameterVariable extends LocalVariable {
7272
7449
  }
7273
7450
  if (this.knownValue === null) {
7274
7451
  this.knownValue = argument;
7275
- this.knownValueLiteral = argument.getLiteralValueAtPath(EMPTY_PATH, SHARED_RECURSION_TRACKER, this);
7452
+ this.knownValueLiteral = argument.getLiteralValueAtPath(this.initPath, SHARED_RECURSION_TRACKER, this);
7276
7453
  return;
7277
7454
  }
7278
7455
  // the same literal or identifier, do nothing
@@ -7288,7 +7465,7 @@ class ParameterVariable extends LocalVariable {
7288
7465
  return;
7289
7466
  }
7290
7467
  // add tracking for the new argument
7291
- const newValue = argument.getLiteralValueAtPath(EMPTY_PATH, SHARED_RECURSION_TRACKER, this);
7468
+ const newValue = argument.getLiteralValueAtPath(this.initPath, SHARED_RECURSION_TRACKER, this);
7292
7469
  if (newValue !== oldValue) {
7293
7470
  this.markReassigned();
7294
7471
  }
@@ -7306,24 +7483,31 @@ class ParameterVariable extends LocalVariable {
7306
7483
  return this.frozenValue;
7307
7484
  }
7308
7485
  getLiteralValueAtPath(path, recursionTracker, origin) {
7309
- if (this.isReassigned) {
7486
+ if (this.isReassigned || path.length + this.initPath.length > MAX_PATH_DEPTH) {
7310
7487
  return UnknownValue;
7311
7488
  }
7312
7489
  const knownValue = this.getKnownValue();
7313
- this.expressionsUseTheKnownValue.push(origin);
7314
- return recursionTracker.withTrackedEntityAtPath(path, knownValue, () => knownValue.getLiteralValueAtPath(path, recursionTracker, origin), UnknownValue);
7490
+ this.expressionsDependingOnKnownValue.push(origin);
7491
+ return recursionTracker.withTrackedEntityAtPath(path, knownValue, () => knownValue.getLiteralValueAtPath([...this.initPath, ...path], recursionTracker, origin), UnknownValue);
7315
7492
  }
7316
7493
  hasEffectsOnInteractionAtPath(path, interaction, context) {
7317
- if (this.isReassigned || interaction.type === INTERACTION_ASSIGNED) {
7494
+ const { type } = interaction;
7495
+ if (this.isReassigned ||
7496
+ type === INTERACTION_ASSIGNED ||
7497
+ path.length + this.initPath.length > MAX_PATH_DEPTH) {
7318
7498
  return super.hasEffectsOnInteractionAtPath(path, interaction, context);
7319
7499
  }
7320
- const knownValue = this.getKnownValue();
7321
- return knownValue.hasEffectsOnInteractionAtPath(path, interaction, context);
7500
+ return (!(type === INTERACTION_CALLED
7501
+ ? (interaction.withNew
7502
+ ? context.instantiated
7503
+ : context.called).trackEntityAtPathAndGetIfTracked(path, interaction.args, this)
7504
+ : context.accessed.trackEntityAtPathAndGetIfTracked(path, this)) &&
7505
+ this.getKnownValue().hasEffectsOnInteractionAtPath([...this.initPath, ...path], interaction, context));
7322
7506
  }
7323
7507
  deoptimizeArgumentsOnInteractionAtPath(interaction, path) {
7324
7508
  // For performance reasons, we fully deoptimize all deeper interactions
7325
7509
  if (path.length >= 2 ||
7326
- this.entitiesToBeDeoptimized.has(UNKNOWN_EXPRESSION) ||
7510
+ this.argumentsToBeDeoptimized.has(UNKNOWN_EXPRESSION) ||
7327
7511
  this.deoptimizationInteractions.length >= MAX_TRACKED_INTERACTIONS ||
7328
7512
  (path.length === 1 &&
7329
7513
  (this.deoptimizedFields.has(UnknownKey) ||
@@ -7332,10 +7516,10 @@ class ParameterVariable extends LocalVariable {
7332
7516
  return;
7333
7517
  }
7334
7518
  if (!this.deoptimizations.trackEntityAtPathAndGetIfTracked(path, interaction.args)) {
7335
- for (const entity of this.entitiesToBeDeoptimized) {
7336
- entity.deoptimizeArgumentsOnInteractionAtPath(interaction, path, SHARED_RECURSION_TRACKER);
7519
+ for (const entity of this.argumentsToBeDeoptimized) {
7520
+ entity.deoptimizeArgumentsOnInteractionAtPath(interaction, [...this.initPath, ...path], SHARED_RECURSION_TRACKER);
7337
7521
  }
7338
- if (!this.entitiesToBeDeoptimized.has(UNKNOWN_EXPRESSION)) {
7522
+ if (!this.argumentsToBeDeoptimized.has(UNKNOWN_EXPRESSION)) {
7339
7523
  this.deoptimizationInteractions.push({
7340
7524
  interaction,
7341
7525
  path
@@ -7356,17 +7540,17 @@ class ParameterVariable extends LocalVariable {
7356
7540
  return;
7357
7541
  }
7358
7542
  this.deoptimizedFields.add(key);
7359
- for (const entity of this.entitiesToBeDeoptimized) {
7543
+ for (const entity of this.argumentsToBeDeoptimized) {
7360
7544
  // We do not need a recursion tracker here as we already track whether
7361
7545
  // this field is deoptimized
7362
- entity.deoptimizePath([key]);
7546
+ entity.deoptimizePath([...this.initPath, key]);
7363
7547
  }
7364
7548
  if (key === UnknownKey) {
7365
7549
  // save some memory
7366
7550
  this.deoptimizationInteractions = NO_INTERACTIONS;
7367
7551
  this.deoptimizations = EMPTY_PATH_TRACKER;
7368
7552
  this.deoptimizedFields = UNKNOWN_DEOPTIMIZED_FIELD;
7369
- this.entitiesToBeDeoptimized = UNKNOWN_DEOPTIMIZED_ENTITY;
7553
+ this.argumentsToBeDeoptimized = UNKNOWN_DEOPTIMIZED_ENTITY;
7370
7554
  }
7371
7555
  }
7372
7556
  getReturnExpressionWhenCalledAtPath(path) {
@@ -7381,11 +7565,14 @@ class ParameterVariable extends LocalVariable {
7381
7565
  }
7382
7566
  return UNKNOWN_RETURN_EXPRESSION;
7383
7567
  }
7568
+ includeArgumentPaths(entity, context) {
7569
+ this.includedPathTracker.includeAllPaths(entity, context, this.initPath);
7570
+ }
7384
7571
  }
7385
7572
 
7386
7573
  class ThisVariable extends ParameterVariable {
7387
7574
  constructor(context) {
7388
- super('this', null, context);
7575
+ super('this', null, EMPTY_PATH, context);
7389
7576
  }
7390
7577
  hasEffectsOnInteractionAtPath(path, interaction, context) {
7391
7578
  return (context.replacedVariableInits.get(this) || UNKNOWN_EXPRESSION).hasEffectsOnInteractionAtPath(path, interaction, context);
@@ -7397,7 +7584,7 @@ class CatchBodyScope extends ChildScope {
7397
7584
  super(parent, parent.context);
7398
7585
  this.parent = parent;
7399
7586
  }
7400
- addDeclaration(identifier, context, init, kind) {
7587
+ addDeclaration(identifier, context, init, destructuredInitPath, kind) {
7401
7588
  if (kind === 'var') {
7402
7589
  const name = identifier.name;
7403
7590
  const existingVariable = this.hoistedVariables?.get(name) || this.variables.get(name);
@@ -7410,7 +7597,7 @@ class CatchBodyScope extends ChildScope {
7410
7597
  // the assignment actually goes to the parameter and the var is
7411
7598
  // hoisted without assignment. Locally, it is shadowed by the
7412
7599
  // parameter
7413
- const declaredVariable = this.parent.parent.addDeclaration(identifier, context, UNDEFINED_EXPRESSION, kind);
7600
+ const declaredVariable = this.parent.parent.addDeclaration(identifier, context, UNDEFINED_EXPRESSION, destructuredInitPath, kind);
7414
7601
  // To avoid the need to rewrite the declaration, we link the variable
7415
7602
  // names. If we ever implement a logic that splits initialization and
7416
7603
  // assignment for hoisted vars, the "renderLikeHoisted" logic can be
@@ -7429,7 +7616,7 @@ class CatchBodyScope extends ChildScope {
7429
7616
  return context.error(parseAst_js.logRedeclarationError(name), identifier.start);
7430
7617
  }
7431
7618
  // We only add parameters to parameter scopes
7432
- const declaredVariable = this.parent.parent.addDeclaration(identifier, context, init, kind);
7619
+ const declaredVariable = this.parent.parent.addDeclaration(identifier, context, init, destructuredInitPath, kind);
7433
7620
  // Necessary to make sure the init is deoptimized for conditional declarations.
7434
7621
  // We cannot call deoptimizePath here.
7435
7622
  declaredVariable.markInitializersForDeoptimization();
@@ -7437,7 +7624,7 @@ class CatchBodyScope extends ChildScope {
7437
7624
  this.addHoistedVariable(name, declaredVariable);
7438
7625
  return declaredVariable;
7439
7626
  }
7440
- return super.addDeclaration(identifier, context, init, kind);
7627
+ return super.addDeclaration(identifier, context, init, destructuredInitPath, kind);
7441
7628
  }
7442
7629
  }
7443
7630
 
@@ -7447,7 +7634,7 @@ class FunctionBodyScope extends ChildScope {
7447
7634
  }
7448
7635
  // There is stuff that is only allowed in function scopes, i.e. functions can
7449
7636
  // be redeclared, functions and var can redeclare each other
7450
- addDeclaration(identifier, context, init, kind) {
7637
+ addDeclaration(identifier, context, init, destructuredInitPath, kind) {
7451
7638
  const name = identifier.name;
7452
7639
  const existingVariable = this.hoistedVariables?.get(name) || this.variables.get(name);
7453
7640
  if (existingVariable) {
@@ -7459,7 +7646,7 @@ class FunctionBodyScope extends ChildScope {
7459
7646
  }
7460
7647
  context.error(parseAst_js.logRedeclarationError(name), identifier.start);
7461
7648
  }
7462
- const newVariable = new LocalVariable(identifier.name, identifier, init, context, kind);
7649
+ const newVariable = new LocalVariable(identifier.name, identifier, init, destructuredInitPath, context, kind);
7463
7650
  this.variables.set(name, newVariable);
7464
7651
  return newVariable;
7465
7652
  }
@@ -7468,21 +7655,21 @@ class FunctionBodyScope extends ChildScope {
7468
7655
  class ParameterScope extends ChildScope {
7469
7656
  constructor(parent, isCatchScope) {
7470
7657
  super(parent, parent.context);
7471
- this.parameters = [];
7472
7658
  this.hasRest = false;
7659
+ this.parameters = [];
7473
7660
  this.bodyScope = isCatchScope ? new CatchBodyScope(this) : new FunctionBodyScope(this);
7474
7661
  }
7475
7662
  /**
7476
7663
  * Adds a parameter to this scope. Parameters must be added in the correct
7477
7664
  * order, i.e. from left to right.
7478
7665
  */
7479
- addParameterDeclaration(identifier) {
7666
+ addParameterDeclaration(identifier, argumentPath) {
7480
7667
  const { name, start } = identifier;
7481
7668
  const existingParameter = this.variables.get(name);
7482
7669
  if (existingParameter) {
7483
7670
  return this.context.error(parseAst_js.logDuplicateArgumentNameError(name), start);
7484
7671
  }
7485
- const variable = new ParameterVariable(name, identifier, this.context);
7672
+ const variable = new ParameterVariable(name, identifier, argumentPath, this.context);
7486
7673
  this.variables.set(name, variable);
7487
7674
  // We also add it to the body scope to detect name conflicts with local
7488
7675
  // variables. We still need the intermediate scope, though, as parameter
@@ -7500,42 +7687,56 @@ class ParameterScope extends ChildScope {
7500
7687
  }
7501
7688
  this.hasRest = hasRest;
7502
7689
  }
7503
- includeCallArguments(context, parameters) {
7690
+ includeCallArguments(context, interaction) {
7504
7691
  let calledFromTryStatement = false;
7505
7692
  let argumentIncluded = false;
7506
7693
  const restParameter = this.hasRest && this.parameters[this.parameters.length - 1];
7507
- for (const checkedArgument of parameters) {
7508
- if (checkedArgument instanceof SpreadElement) {
7509
- for (const argument of parameters) {
7510
- argument.include(context, false);
7511
- }
7512
- break;
7694
+ const { args } = interaction;
7695
+ let lastExplicitlyIncludedIndex = args.length - 1;
7696
+ // If there is a SpreadElement, we need to include all arguments after it
7697
+ // because we no longer know which argument corresponds to which parameter.
7698
+ for (let argumentIndex = 1; argumentIndex < args.length; argumentIndex++) {
7699
+ const argument = args[argumentIndex];
7700
+ if (argument instanceof SpreadElement && !argumentIncluded) {
7701
+ argumentIncluded = true;
7702
+ lastExplicitlyIncludedIndex = argumentIndex - 1;
7703
+ }
7704
+ if (argumentIncluded) {
7705
+ argument.includePath(UNKNOWN_PATH, context);
7706
+ argument.include(context, false);
7513
7707
  }
7514
7708
  }
7515
- for (let index = parameters.length - 1; index >= 0; index--) {
7516
- const parameterVariables = this.parameters[index] || restParameter;
7517
- const argument = parameters[index];
7709
+ // Now we go backwards either starting from the last argument or before the
7710
+ // first SpreadElement to ensure all arguments before are included as needed
7711
+ for (let index = lastExplicitlyIncludedIndex; index >= 1; index--) {
7712
+ const parameterVariables = this.parameters[index - 1] || restParameter;
7713
+ const argument = args[index];
7518
7714
  if (parameterVariables) {
7519
7715
  calledFromTryStatement = false;
7520
7716
  if (parameterVariables.length === 0) {
7521
- // handle empty destructuring
7717
+ // handle empty destructuring to avoid destructuring undefined
7522
7718
  argumentIncluded = true;
7523
7719
  }
7524
7720
  else {
7525
7721
  for (const variable of parameterVariables) {
7526
- if (variable.included) {
7527
- argumentIncluded = true;
7528
- }
7529
7722
  if (variable.calledFromTryStatement) {
7530
7723
  calledFromTryStatement = true;
7531
7724
  }
7725
+ if (variable.included) {
7726
+ argumentIncluded = true;
7727
+ if (calledFromTryStatement) {
7728
+ argument.include(context, true);
7729
+ }
7730
+ else {
7731
+ variable.includeArgumentPaths(argument, context);
7732
+ argument.include(context, false);
7733
+ }
7734
+ }
7532
7735
  }
7533
7736
  }
7534
7737
  }
7535
- if (!argumentIncluded && argument.shouldBeIncluded(context)) {
7738
+ if (!argument.included && (argumentIncluded || argument.shouldBeIncluded(context))) {
7536
7739
  argumentIncluded = true;
7537
- }
7538
- if (argumentIncluded) {
7539
7740
  argument.include(context, calledFromTryStatement);
7540
7741
  }
7541
7742
  }
@@ -7551,11 +7752,62 @@ class ReturnValueScope extends ParameterScope {
7551
7752
  addReturnExpression(expression) {
7552
7753
  this.returnExpressions.push(expression);
7553
7754
  }
7755
+ deoptimizeArgumentsOnCall(interaction) {
7756
+ const { parameters } = this;
7757
+ const { args } = interaction;
7758
+ let position = 0;
7759
+ for (; position < args.length - 1; position++) {
7760
+ // Only the "this" argument arg[0] can be null
7761
+ const argument = args[position + 1];
7762
+ if (argument instanceof SpreadElement) {
7763
+ // This deoptimizes the current and remaining parameters and arguments
7764
+ for (; position < parameters.length; position++) {
7765
+ args[position + 1]?.deoptimizePath(UNKNOWN_PATH);
7766
+ parameters[position].forEach(variable => variable.markReassigned());
7767
+ }
7768
+ break;
7769
+ }
7770
+ if (this.hasRest && position >= parameters.length - 1) {
7771
+ argument.deoptimizePath(UNKNOWN_PATH);
7772
+ }
7773
+ else {
7774
+ const variables = parameters[position];
7775
+ if (variables) {
7776
+ for (const variable of variables) {
7777
+ variable.addArgumentValue(argument);
7778
+ }
7779
+ }
7780
+ this.addArgumentToBeDeoptimized(argument);
7781
+ }
7782
+ }
7783
+ const nonRestParameterLength = this.hasRest ? parameters.length - 1 : parameters.length;
7784
+ for (; position < nonRestParameterLength; position++) {
7785
+ for (const variable of parameters[position]) {
7786
+ variable.addArgumentValue(UNDEFINED_EXPRESSION);
7787
+ }
7788
+ }
7789
+ }
7554
7790
  getReturnExpression() {
7555
7791
  if (this.returnExpression === null)
7556
7792
  this.updateReturnExpression();
7557
7793
  return this.returnExpression;
7558
7794
  }
7795
+ deoptimizeAllParameters() {
7796
+ for (const parameter of this.parameters) {
7797
+ for (const variable of parameter) {
7798
+ variable.deoptimizePath(UNKNOWN_PATH);
7799
+ variable.markReassigned();
7800
+ }
7801
+ }
7802
+ }
7803
+ reassignAllParameters() {
7804
+ for (const parameter of this.parameters) {
7805
+ for (const variable of parameter) {
7806
+ variable.markReassigned();
7807
+ }
7808
+ }
7809
+ }
7810
+ addArgumentToBeDeoptimized(_argument) { }
7559
7811
  updateReturnExpression() {
7560
7812
  if (this.returnExpressions.length === 1) {
7561
7813
  this.returnExpression = this.returnExpressions[0];
@@ -7571,24 +7823,30 @@ class ReturnValueScope extends ParameterScope {
7571
7823
 
7572
7824
  class FunctionScope extends ReturnValueScope {
7573
7825
  constructor(parent) {
7574
- const { context } = parent;
7575
7826
  super(parent, false);
7827
+ const { context } = parent;
7576
7828
  this.variables.set('arguments', (this.argumentsVariable = new ArgumentsVariable(context)));
7577
7829
  this.variables.set('this', (this.thisVariable = new ThisVariable(context)));
7578
7830
  }
7579
7831
  findLexicalBoundary() {
7580
7832
  return this;
7581
7833
  }
7582
- includeCallArguments(context, parameters) {
7583
- super.includeCallArguments(context, parameters);
7834
+ includeCallArguments(context, interaction) {
7835
+ super.includeCallArguments(context, interaction);
7584
7836
  if (this.argumentsVariable.included) {
7585
- for (const argument of parameters) {
7586
- if (!argument.included) {
7837
+ const { args } = interaction;
7838
+ for (let argumentIndex = 1; argumentIndex < args.length; argumentIndex++) {
7839
+ const argument = args[argumentIndex];
7840
+ if (argument) {
7841
+ argument.includePath(UNKNOWN_PATH, context);
7587
7842
  argument.include(context, false);
7588
7843
  }
7589
7844
  }
7590
7845
  }
7591
7846
  }
7847
+ addArgumentToBeDeoptimized(argument) {
7848
+ this.argumentsVariable.addArgumentToBeDeoptimized(argument);
7849
+ }
7592
7850
  }
7593
7851
 
7594
7852
  class ExpressionStatement extends NodeBase {
@@ -7616,8 +7874,9 @@ class ExpressionStatement extends NodeBase {
7616
7874
  return this.parent.type !== parseAst_js.Program;
7617
7875
  return super.shouldBeIncluded(context);
7618
7876
  }
7619
- applyDeoptimizations() { }
7620
7877
  }
7878
+ ExpressionStatement.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
7879
+ ExpressionStatement.prototype.applyDeoptimizations = doNotDeoptimize;
7621
7880
 
7622
7881
  class BlockStatement extends NodeBase {
7623
7882
  get deoptimizeBody() {
@@ -7682,6 +7941,8 @@ class BlockStatement extends NodeBase {
7682
7941
  }
7683
7942
  }
7684
7943
  }
7944
+ BlockStatement.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
7945
+ BlockStatement.prototype.applyDeoptimizations = doNotDeoptimize;
7685
7946
 
7686
7947
  class RestElement extends NodeBase {
7687
7948
  constructor() {
@@ -7691,9 +7952,12 @@ class RestElement extends NodeBase {
7691
7952
  addExportedVariables(variables, exportNamesByVariable) {
7692
7953
  this.argument.addExportedVariables(variables, exportNamesByVariable);
7693
7954
  }
7694
- declare(kind, init) {
7955
+ declare(kind, destructuredInitPath, init) {
7695
7956
  this.declarationInit = init;
7696
- return this.argument.declare(kind, UNKNOWN_EXPRESSION);
7957
+ return this.argument.declare(kind, getIncludedPatternPath$1(destructuredInitPath), init);
7958
+ }
7959
+ deoptimizeAssignment(destructuredInitPath, init) {
7960
+ this.argument.deoptimizeAssignment(getIncludedPatternPath$1(destructuredInitPath), init);
7697
7961
  }
7698
7962
  deoptimizePath(path) {
7699
7963
  if (path.length === 0) {
@@ -7704,6 +7968,20 @@ class RestElement extends NodeBase {
7704
7968
  return (path.length > 0 ||
7705
7969
  this.argument.hasEffectsOnInteractionAtPath(EMPTY_PATH, interaction, context));
7706
7970
  }
7971
+ hasEffectsWhenDestructuring(context, destructuredInitPath, init) {
7972
+ return this.argument.hasEffectsWhenDestructuring(context, getIncludedPatternPath$1(destructuredInitPath), init);
7973
+ }
7974
+ includeDestructuredIfNecessary(context, destructuredInitPath, init) {
7975
+ return (this.included =
7976
+ this.argument.includeDestructuredIfNecessary(context, getIncludedPatternPath$1(destructuredInitPath), init) || this.included);
7977
+ }
7978
+ include(context, includeChildrenRecursively) {
7979
+ if (!this.included)
7980
+ this.includeNode(context);
7981
+ // This should just include the identifier, its properties should be
7982
+ // included where the variable is used.
7983
+ this.argument.include(context, includeChildrenRecursively);
7984
+ }
7707
7985
  markDeclarationReached() {
7708
7986
  this.argument.markDeclarationReached();
7709
7987
  }
@@ -7715,12 +7993,16 @@ class RestElement extends NodeBase {
7715
7993
  }
7716
7994
  }
7717
7995
  }
7996
+ RestElement.prototype.includeNode = onlyIncludeSelf;
7997
+ const getIncludedPatternPath$1 = (destructuredInitPath) => destructuredInitPath.at(-1) === UnknownKey
7998
+ ? destructuredInitPath
7999
+ : [...destructuredInitPath, UnknownKey];
7718
8000
 
7719
8001
  class FunctionBase extends NodeBase {
7720
8002
  constructor() {
7721
8003
  super(...arguments);
7722
- this.objectEntity = null;
7723
8004
  this.parameterVariableValuesDeoptimized = false;
8005
+ this.includeCallArguments = this.scope.includeCallArguments.bind(this.scope);
7724
8006
  }
7725
8007
  get async() {
7726
8008
  return isFlagSet(this.flags, 256 /* Flag.async */);
@@ -7740,53 +8022,9 @@ class FunctionBase extends NodeBase {
7740
8022
  set generator(value) {
7741
8023
  this.flags = setFlag(this.flags, 4194304 /* Flag.generator */, value);
7742
8024
  }
7743
- updateParameterVariableValues(_arguments) {
7744
- for (let position = 0; position < this.params.length; position++) {
7745
- const parameter = this.params[position];
7746
- if (!(parameter instanceof Identifier)) {
7747
- continue;
7748
- }
7749
- const parameterVariable = parameter.variable;
7750
- const argument = _arguments[position + 1] ?? UNDEFINED_EXPRESSION;
7751
- parameterVariable.updateKnownValue(argument);
7752
- }
7753
- }
7754
- deoptimizeParameterVariableValues() {
7755
- for (const parameter of this.params) {
7756
- if (parameter instanceof Identifier) {
7757
- const parameterVariable = parameter.variable;
7758
- parameterVariable.markReassigned();
7759
- }
7760
- }
7761
- }
7762
8025
  deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
7763
- if (interaction.type === INTERACTION_CALLED) {
7764
- const { parameters } = this.scope;
7765
- const { args } = interaction;
7766
- let hasRest = false;
7767
- for (let position = 0; position < args.length - 1; position++) {
7768
- const parameter = this.params[position];
7769
- // Only the "this" argument arg[0] can be null
7770
- const argument = args[position + 1];
7771
- if (argument instanceof SpreadElement) {
7772
- this.deoptimizeParameterVariableValues();
7773
- }
7774
- if (hasRest || parameter instanceof RestElement) {
7775
- hasRest = true;
7776
- argument.deoptimizePath(UNKNOWN_PATH);
7777
- }
7778
- else if (parameter instanceof Identifier) {
7779
- parameters[position][0].addEntityToBeDeoptimized(argument);
7780
- this.addArgumentToBeDeoptimized(argument);
7781
- }
7782
- else if (parameter) {
7783
- argument.deoptimizePath(UNKNOWN_PATH);
7784
- }
7785
- else {
7786
- this.addArgumentToBeDeoptimized(argument);
7787
- }
7788
- }
7789
- this.updateParameterVariableValues(args);
8026
+ if (interaction.type === INTERACTION_CALLED && path.length === 0) {
8027
+ this.scope.deoptimizeArgumentsOnCall(interaction);
7790
8028
  }
7791
8029
  else {
7792
8030
  this.getObjectEntity().deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker);
@@ -7798,12 +8036,7 @@ class FunctionBase extends NodeBase {
7798
8036
  // A reassignment of UNKNOWN_PATH is considered equivalent to having lost track
7799
8037
  // which means the return expression and parameters need to be reassigned
7800
8038
  this.scope.getReturnExpression().deoptimizePath(UNKNOWN_PATH);
7801
- for (const parameterList of this.scope.parameters) {
7802
- for (const parameter of parameterList) {
7803
- parameter.deoptimizePath(UNKNOWN_PATH);
7804
- parameter.markReassigned();
7805
- }
7806
- }
8039
+ this.scope.deoptimizeAllParameters();
7807
8040
  }
7808
8041
  }
7809
8042
  getLiteralValueAtPath(path, recursionTracker, origin) {
@@ -7841,8 +8074,13 @@ class FunctionBase extends NodeBase {
7841
8074
  return true;
7842
8075
  }
7843
8076
  }
7844
- for (const parameter of this.params) {
7845
- if (parameter.hasEffects(context))
8077
+ const { propertyReadSideEffects } = this.scope.context.options
8078
+ .treeshake;
8079
+ for (let index = 0; index < this.params.length; index++) {
8080
+ const parameter = this.params[index];
8081
+ if (parameter.hasEffects(context) ||
8082
+ (propertyReadSideEffects &&
8083
+ parameter.hasEffectsWhenDestructuring(context, EMPTY_PATH, interaction.args[index + 1] || UNDEFINED_EXPRESSION)))
7846
8084
  return true;
7847
8085
  }
7848
8086
  return false;
@@ -7861,21 +8099,17 @@ class FunctionBase extends NodeBase {
7861
8099
  return variable?.getOnlyFunctionCallUsed() ?? false;
7862
8100
  }
7863
8101
  include(context, includeChildrenRecursively) {
7864
- if (!this.parameterVariableValuesDeoptimized && !this.onlyFunctionCallUsed()) {
8102
+ if (!this.included)
8103
+ this.includeNode(context);
8104
+ if (!(this.parameterVariableValuesDeoptimized || this.onlyFunctionCallUsed())) {
7865
8105
  this.parameterVariableValuesDeoptimized = true;
7866
- this.deoptimizeParameterVariableValues();
8106
+ this.scope.reassignAllParameters();
7867
8107
  }
7868
- if (!this.deoptimized)
7869
- this.applyDeoptimizations();
7870
- this.included = true;
7871
8108
  const { brokenFlow } = context;
7872
8109
  context.brokenFlow = false;
7873
8110
  this.body.include(context, includeChildrenRecursively);
7874
8111
  context.brokenFlow = brokenFlow;
7875
8112
  }
7876
- includeCallArguments(context, parameters) {
7877
- this.scope.includeCallArguments(context, parameters);
7878
- }
7879
8113
  initialise() {
7880
8114
  super.initialise();
7881
8115
  if (this.body instanceof BlockStatement) {
@@ -7897,14 +8131,14 @@ class FunctionBase extends NodeBase {
7897
8131
  // so that the scope already knows all parameters and can detect conflicts
7898
8132
  // when parsing the body.
7899
8133
  const parameters = (this.params = params.map((parameter) => new (context.getNodeConstructor(parameter.type))(this, scope).parseNode(parameter)));
7900
- scope.addParameterVariables(parameters.map(parameter => parameter.declare('parameter', UNKNOWN_EXPRESSION)), parameters[parameters.length - 1] instanceof RestElement);
8134
+ scope.addParameterVariables(parameters.map(parameter => parameter.declare('parameter', EMPTY_PATH, UNKNOWN_EXPRESSION)), parameters[parameters.length - 1] instanceof RestElement);
7901
8135
  this.body = new (context.getNodeConstructor(body.type))(this, bodyScope).parseNode(body);
7902
8136
  return super.parseNode(esTreeNode);
7903
8137
  }
7904
- addArgumentToBeDeoptimized(_argument) { }
7905
- applyDeoptimizations() { }
7906
8138
  }
7907
8139
  FunctionBase.prototype.preventChildBlockScope = true;
8140
+ FunctionBase.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
8141
+ FunctionBase.prototype.applyDeoptimizations = doNotDeoptimize;
7908
8142
 
7909
8143
  class FunctionNode extends FunctionBase {
7910
8144
  constructor() {
@@ -7916,18 +8150,16 @@ class FunctionNode extends FunctionBase {
7916
8150
  this.constructedEntity = new ObjectEntity(Object.create(null), OBJECT_PROTOTYPE);
7917
8151
  // This makes sure that all deoptimizations of "this" are applied to the
7918
8152
  // constructed entity.
7919
- this.scope.thisVariable.addEntityToBeDeoptimized(this.constructedEntity);
8153
+ this.scope.thisVariable.addArgumentValue(this.constructedEntity);
7920
8154
  }
7921
8155
  deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
7922
8156
  super.deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker);
7923
8157
  if (interaction.type === INTERACTION_CALLED && path.length === 0 && interaction.args[0]) {
7924
8158
  // args[0] is the "this" argument
7925
- this.scope.thisVariable.addEntityToBeDeoptimized(interaction.args[0]);
8159
+ this.scope.thisVariable.addArgumentValue(interaction.args[0]);
7926
8160
  }
7927
8161
  }
7928
8162
  hasEffects(context) {
7929
- if (!this.deoptimized)
7930
- this.applyDeoptimizations();
7931
8163
  if (this.annotationNoSideEffects) {
7932
8164
  return false;
7933
8165
  }
@@ -7965,7 +8197,7 @@ class FunctionNode extends FunctionBase {
7965
8197
  }
7966
8198
  include(context, includeChildrenRecursively) {
7967
8199
  super.include(context, includeChildrenRecursively);
7968
- this.id?.include();
8200
+ this.id?.include(context);
7969
8201
  const hasArguments = this.scope.argumentsVariable.included;
7970
8202
  for (const parameter of this.params) {
7971
8203
  if (!(parameter instanceof Identifier) || hasArguments) {
@@ -7973,12 +8205,18 @@ class FunctionNode extends FunctionBase {
7973
8205
  }
7974
8206
  }
7975
8207
  }
8208
+ includeNode(context) {
8209
+ this.included = true;
8210
+ const hasArguments = this.scope.argumentsVariable.included;
8211
+ for (const parameter of this.params) {
8212
+ if (!(parameter instanceof Identifier) || hasArguments) {
8213
+ parameter.includePath(UNKNOWN_PATH, context);
8214
+ }
8215
+ }
8216
+ }
7976
8217
  initialise() {
7977
8218
  super.initialise();
7978
- this.id?.declare('function', this);
7979
- }
7980
- addArgumentToBeDeoptimized(argument) {
7981
- this.scope.argumentsVariable.addArgumentToBeDeoptimized(argument);
8219
+ this.id?.declare('function', EMPTY_PATH, this);
7982
8220
  }
7983
8221
  getObjectEntity() {
7984
8222
  if (this.objectEntity !== null) {
@@ -8028,11 +8266,16 @@ function getFunctionIdInsertPosition(code, start) {
8028
8266
  }
8029
8267
  class ExportDefaultDeclaration extends NodeBase {
8030
8268
  include(context, includeChildrenRecursively) {
8031
- super.include(context, includeChildrenRecursively);
8269
+ this.included = true;
8270
+ this.declaration.include(context, includeChildrenRecursively);
8032
8271
  if (includeChildrenRecursively) {
8033
- this.scope.context.includeVariableInModule(this.variable);
8272
+ this.scope.context.includeVariableInModule(this.variable, UNKNOWN_PATH, context);
8034
8273
  }
8035
8274
  }
8275
+ includePath(path, context) {
8276
+ this.included = true;
8277
+ this.declaration.includePath(path, context);
8278
+ }
8036
8279
  initialise() {
8037
8280
  super.initialise();
8038
8281
  const declaration = this.declaration;
@@ -8077,7 +8320,6 @@ class ExportDefaultDeclaration extends NodeBase {
8077
8320
  }
8078
8321
  this.declaration.render(code, options);
8079
8322
  }
8080
- applyDeoptimizations() { }
8081
8323
  renderNamedDeclaration(code, declarationStart, idInsertPosition, options) {
8082
8324
  const { exportNamesByVariable, format, snippets: { getPropertyAccess } } = options;
8083
8325
  const name = this.variable.getName(getPropertyAccess);
@@ -8108,6 +8350,8 @@ class ExportDefaultDeclaration extends NodeBase {
8108
8350
  }
8109
8351
  }
8110
8352
  ExportDefaultDeclaration.prototype.needsBoundaries = true;
8353
+ ExportDefaultDeclaration.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
8354
+ ExportDefaultDeclaration.prototype.applyDeoptimizations = doNotDeoptimize;
8111
8355
 
8112
8356
  const needsEscapeRegEx = /[\n\r'\\\u2028\u2029]/;
8113
8357
  const quoteNewlineRegEx = /([\n\r'\u2028\u2029])/g;
@@ -8377,6 +8621,7 @@ class Literal extends NodeBase {
8377
8621
  }
8378
8622
  }
8379
8623
  }
8624
+ Literal.prototype.includeNode = onlyIncludeSelf;
8380
8625
 
8381
8626
  function getChainElementLiteralValueAtPath(element, object, path, recursionTracker, origin) {
8382
8627
  if ('getLiteralValueAtPathAsChainElement' in object) {
@@ -8392,8 +8637,6 @@ function getChainElementLiteralValueAtPath(element, object, path, recursionTrack
8392
8637
  return element.getLiteralValueAtPath(path, recursionTracker, origin);
8393
8638
  }
8394
8639
 
8395
- // To avoid infinite recursions
8396
- const MAX_PATH_DEPTH = 7;
8397
8640
  function getResolvablePropertyKey(memberExpression) {
8398
8641
  return memberExpression.computed
8399
8642
  ? getResolvableComputedPropertyKey(memberExpression.property)
@@ -8492,18 +8735,27 @@ class MemberExpression extends NodeBase {
8492
8735
  }
8493
8736
  else if (!this.isUndefined) {
8494
8737
  if (path.length < MAX_PATH_DEPTH) {
8495
- this.object.deoptimizeArgumentsOnInteractionAtPath(interaction, [this.getPropertyKey(), ...path], recursionTracker);
8738
+ this.object.deoptimizeArgumentsOnInteractionAtPath(interaction, this.propertyKey === UnknownKey ? UNKNOWN_PATH : [this.propertyKey, ...path], recursionTracker);
8496
8739
  }
8497
8740
  else {
8498
8741
  deoptimizeInteraction(interaction);
8499
8742
  }
8500
8743
  }
8501
8744
  }
8745
+ deoptimizeAssignment(destructuredInitPath, init) {
8746
+ this.deoptimizePath(EMPTY_PATH);
8747
+ init.deoptimizePath([...destructuredInitPath, UnknownKey]);
8748
+ }
8502
8749
  deoptimizeCache() {
8750
+ if (this.propertyKey === this.dynamicPropertyKey)
8751
+ return;
8503
8752
  const { expressionsToBeDeoptimized, object } = this;
8504
8753
  this.expressionsToBeDeoptimized = parseAst_js.EMPTY_ARRAY;
8505
- this.propertyKey = UnknownKey;
8754
+ this.dynamicPropertyKey = this.propertyKey;
8506
8755
  object.deoptimizePath(UNKNOWN_PATH);
8756
+ if (this.included) {
8757
+ object.includePath(UNKNOWN_PATH, createInclusionContext());
8758
+ }
8507
8759
  for (const expression of expressionsToBeDeoptimized) {
8508
8760
  expression.deoptimizeCache();
8509
8761
  }
@@ -8514,11 +8766,13 @@ class MemberExpression extends NodeBase {
8514
8766
  if (this.variable) {
8515
8767
  this.variable.deoptimizePath(path);
8516
8768
  }
8517
- else if (!this.isUndefined && path.length < MAX_PATH_DEPTH) {
8518
- const propertyKey = this.getPropertyKey();
8769
+ else if (!this.isUndefined) {
8770
+ const { propertyKey } = this;
8519
8771
  this.object.deoptimizePath([
8520
8772
  propertyKey === UnknownKey ? UnknownNonAccessorKey : propertyKey,
8521
- ...path
8773
+ ...(path.length < MAX_PATH_DEPTH
8774
+ ? path
8775
+ : [...path.slice(0, MAX_PATH_DEPTH), UnknownKey])
8522
8776
  ]);
8523
8777
  }
8524
8778
  }
@@ -8529,9 +8783,11 @@ class MemberExpression extends NodeBase {
8529
8783
  if (this.isUndefined) {
8530
8784
  return undefined;
8531
8785
  }
8532
- if (this.propertyKey !== UnknownKey && path.length < MAX_PATH_DEPTH) {
8533
- this.expressionsToBeDeoptimized.push(origin);
8534
- return this.object.getLiteralValueAtPath([this.getPropertyKey(), ...path], recursionTracker, origin);
8786
+ const propertyKey = this.getDynamicPropertyKey();
8787
+ if (propertyKey !== UnknownKey && path.length < MAX_PATH_DEPTH) {
8788
+ if (propertyKey !== this.propertyKey)
8789
+ this.expressionsToBeDeoptimized.push(origin);
8790
+ return this.object.getLiteralValueAtPath([propertyKey, ...path], recursionTracker, origin);
8535
8791
  }
8536
8792
  return UnknownValue;
8537
8793
  }
@@ -8551,9 +8807,11 @@ class MemberExpression extends NodeBase {
8551
8807
  if (this.isUndefined) {
8552
8808
  return [UNDEFINED_EXPRESSION, false];
8553
8809
  }
8554
- if (this.propertyKey !== UnknownKey && path.length < MAX_PATH_DEPTH) {
8555
- this.expressionsToBeDeoptimized.push(origin);
8556
- return this.object.getReturnExpressionWhenCalledAtPath([this.getPropertyKey(), ...path], interaction, recursionTracker, origin);
8810
+ const propertyKey = this.getDynamicPropertyKey();
8811
+ if (propertyKey !== UnknownKey && path.length < MAX_PATH_DEPTH) {
8812
+ if (propertyKey !== this.propertyKey)
8813
+ this.expressionsToBeDeoptimized.push(origin);
8814
+ return this.object.getReturnExpressionWhenCalledAtPath([propertyKey, ...path], interaction, recursionTracker, origin);
8557
8815
  }
8558
8816
  return UNKNOWN_RETURN_EXPRESSION;
8559
8817
  }
@@ -8599,14 +8857,45 @@ class MemberExpression extends NodeBase {
8599
8857
  return true;
8600
8858
  }
8601
8859
  if (path.length < MAX_PATH_DEPTH) {
8602
- return this.object.hasEffectsOnInteractionAtPath([this.getPropertyKey(), ...path], interaction, context);
8860
+ return this.object.hasEffectsOnInteractionAtPath([this.getDynamicPropertyKey(), ...path], interaction, context);
8603
8861
  }
8604
8862
  return true;
8605
8863
  }
8864
+ hasEffectsWhenDestructuring(context, destructuredInitPath, init) {
8865
+ return (destructuredInitPath.length > 0 &&
8866
+ init.hasEffectsOnInteractionAtPath(destructuredInitPath, NODE_INTERACTION_UNKNOWN_ACCESS, context));
8867
+ }
8606
8868
  include(context, includeChildrenRecursively) {
8869
+ if (!this.included)
8870
+ this.includeNode(context);
8871
+ this.object.include(context, includeChildrenRecursively);
8872
+ this.property.include(context, includeChildrenRecursively);
8873
+ }
8874
+ includeNode(context) {
8875
+ this.included = true;
8607
8876
  if (!this.deoptimized)
8608
8877
  this.applyDeoptimizations();
8609
- this.includeProperties(context, includeChildrenRecursively);
8878
+ if (this.variable) {
8879
+ this.scope.context.includeVariableInModule(this.variable, EMPTY_PATH, context);
8880
+ }
8881
+ else if (!this.isUndefined) {
8882
+ this.object.includePath([this.propertyKey], context);
8883
+ }
8884
+ }
8885
+ includePath(path, context) {
8886
+ if (!this.included)
8887
+ this.includeNode(context);
8888
+ if (this.variable) {
8889
+ this.variable?.includePath(path, context);
8890
+ }
8891
+ else if (!this.isUndefined) {
8892
+ this.object.includePath([
8893
+ this.propertyKey,
8894
+ ...(path.length < MAX_PATH_DEPTH
8895
+ ? path
8896
+ : [...path.slice(0, MAX_PATH_DEPTH), UnknownKey])
8897
+ ], context);
8898
+ }
8610
8899
  }
8611
8900
  includeAsAssignmentTarget(context, includeChildrenRecursively, deoptimizeAccess) {
8612
8901
  if (!this.assignmentDeoptimized)
@@ -8615,20 +8904,34 @@ class MemberExpression extends NodeBase {
8615
8904
  this.include(context, includeChildrenRecursively);
8616
8905
  }
8617
8906
  else {
8618
- this.includeProperties(context, includeChildrenRecursively);
8907
+ if (!this.included)
8908
+ this.includeNode(context);
8909
+ this.object.include(context, includeChildrenRecursively);
8910
+ this.property.include(context, includeChildrenRecursively);
8619
8911
  }
8620
8912
  }
8621
- includeCallArguments(context, parameters) {
8913
+ includeCallArguments(context, interaction) {
8622
8914
  if (this.variable) {
8623
- this.variable.includeCallArguments(context, parameters);
8915
+ this.variable.includeCallArguments(context, interaction);
8624
8916
  }
8625
8917
  else {
8626
- super.includeCallArguments(context, parameters);
8918
+ super.includeCallArguments(context, interaction);
8919
+ }
8920
+ }
8921
+ includeDestructuredIfNecessary(context, destructuredInitPath, init) {
8922
+ if ((this.included ||=
8923
+ destructuredInitPath.length > 0 &&
8924
+ !context.brokenFlow &&
8925
+ init.hasEffectsOnInteractionAtPath(destructuredInitPath, NODE_INTERACTION_UNKNOWN_ACCESS, createHasEffectsContext()))) {
8926
+ init.include(context, false);
8927
+ return true;
8627
8928
  }
8929
+ return false;
8628
8930
  }
8629
8931
  initialise() {
8630
8932
  super.initialise();
8631
- this.propertyKey = getResolvablePropertyKey(this);
8933
+ this.dynamicPropertyKey = getResolvablePropertyKey(this);
8934
+ this.propertyKey = this.dynamicPropertyKey === null ? UnknownKey : this.dynamicPropertyKey;
8632
8935
  this.accessInteraction = { args: [this.object], type: INTERACTION_ACCESSED };
8633
8936
  }
8634
8937
  render(code, options, { renderedParentType, isCalleeOfRenderedParent, renderedSurroundingElement } = parseAst_js.BLANK) {
@@ -8665,8 +8968,7 @@ class MemberExpression extends NodeBase {
8665
8968
  this.bound &&
8666
8969
  propertyReadSideEffects &&
8667
8970
  !(this.variable || this.isUndefined)) {
8668
- const propertyKey = this.getPropertyKey();
8669
- this.object.deoptimizeArgumentsOnInteractionAtPath(this.accessInteraction, [propertyKey], SHARED_RECURSION_TRACKER);
8971
+ this.object.deoptimizeArgumentsOnInteractionAtPath(this.accessInteraction, [this.propertyKey], SHARED_RECURSION_TRACKER);
8670
8972
  this.scope.context.requestTreeshakingPass();
8671
8973
  }
8672
8974
  if (this.variable) {
@@ -8683,7 +8985,7 @@ class MemberExpression extends NodeBase {
8683
8985
  this.bound &&
8684
8986
  propertyReadSideEffects &&
8685
8987
  !(this.variable || this.isUndefined)) {
8686
- this.object.deoptimizeArgumentsOnInteractionAtPath(this.assignmentInteraction, [this.getPropertyKey()], SHARED_RECURSION_TRACKER);
8988
+ this.object.deoptimizeArgumentsOnInteractionAtPath(this.assignmentInteraction, [this.propertyKey], SHARED_RECURSION_TRACKER);
8687
8989
  this.scope.context.requestTreeshakingPass();
8688
8990
  }
8689
8991
  }
@@ -8692,24 +8994,24 @@ class MemberExpression extends NodeBase {
8692
8994
  const variable = this.scope.findVariable(this.object.name);
8693
8995
  if (variable.isNamespace) {
8694
8996
  if (this.variable) {
8695
- this.scope.context.includeVariableInModule(this.variable);
8997
+ this.scope.context.includeVariableInModule(this.variable, UNKNOWN_PATH, createInclusionContext());
8696
8998
  }
8697
8999
  this.scope.context.log(parseAst_js.LOGLEVEL_WARN, parseAst_js.logIllegalImportReassignment(this.object.name, this.scope.context.module.id), this.start);
8698
9000
  }
8699
9001
  }
8700
9002
  }
8701
- getPropertyKey() {
8702
- if (this.propertyKey === null) {
8703
- this.propertyKey = UnknownKey;
9003
+ getDynamicPropertyKey() {
9004
+ if (this.dynamicPropertyKey === null) {
9005
+ this.dynamicPropertyKey = this.propertyKey;
8704
9006
  const value = this.property.getLiteralValueAtPath(EMPTY_PATH, SHARED_RECURSION_TRACKER, this);
8705
- return (this.propertyKey =
9007
+ return (this.dynamicPropertyKey =
8706
9008
  value === SymbolToStringTag
8707
9009
  ? value
8708
9010
  : typeof value === 'symbol'
8709
9011
  ? UnknownKey
8710
9012
  : String(value));
8711
9013
  }
8712
- return this.propertyKey;
9014
+ return this.dynamicPropertyKey;
8713
9015
  }
8714
9016
  hasAccessEffect(context) {
8715
9017
  const { propertyReadSideEffects } = this.scope.context.options
@@ -8717,17 +9019,7 @@ class MemberExpression extends NodeBase {
8717
9019
  return (!(this.variable || this.isUndefined) &&
8718
9020
  propertyReadSideEffects &&
8719
9021
  (propertyReadSideEffects === 'always' ||
8720
- this.object.hasEffectsOnInteractionAtPath([this.getPropertyKey()], this.accessInteraction, context)));
8721
- }
8722
- includeProperties(context, includeChildrenRecursively) {
8723
- if (!this.included) {
8724
- this.included = true;
8725
- if (this.variable) {
8726
- this.scope.context.includeVariableInModule(this.variable);
8727
- }
8728
- }
8729
- this.object.include(context, includeChildrenRecursively);
8730
- this.property.include(context, includeChildrenRecursively);
9022
+ this.object.hasEffectsOnInteractionAtPath([this.getDynamicPropertyKey()], this.accessInteraction, context)));
8731
9023
  }
8732
9024
  }
8733
9025
  function resolveNamespaceVariables(baseVariable, path, astContext) {
@@ -8771,18 +9063,20 @@ class MetaProperty extends NodeBase {
8771
9063
  return path.length > 1 || type !== INTERACTION_ACCESSED;
8772
9064
  }
8773
9065
  include() {
8774
- if (!this.included) {
8775
- this.included = true;
8776
- if (this.meta.name === IMPORT) {
8777
- this.scope.context.addImportMeta(this);
8778
- const parent = this.parent;
8779
- const metaProperty = (this.metaProperty =
8780
- parent instanceof MemberExpression && typeof parent.propertyKey === 'string'
8781
- ? parent.propertyKey
8782
- : null);
8783
- if (metaProperty?.startsWith(FILE_PREFIX)) {
8784
- this.referenceId = metaProperty.slice(FILE_PREFIX.length);
8785
- }
9066
+ if (!this.included)
9067
+ this.includeNode();
9068
+ }
9069
+ includeNode() {
9070
+ this.included = true;
9071
+ if (this.meta.name === IMPORT) {
9072
+ this.scope.context.addImportMeta(this);
9073
+ const parent = this.parent;
9074
+ const metaProperty = (this.metaProperty =
9075
+ parent instanceof MemberExpression && typeof parent.propertyKey === 'string'
9076
+ ? parent.propertyKey
9077
+ : null);
9078
+ if (metaProperty?.startsWith(FILE_PREFIX)) {
9079
+ this.referenceId = metaProperty.slice(FILE_PREFIX.length);
8786
9080
  }
8787
9081
  }
8788
9082
  }
@@ -8889,7 +9183,7 @@ class UndefinedVariable extends Variable {
8889
9183
 
8890
9184
  class ExportDefaultVariable extends LocalVariable {
8891
9185
  constructor(name, exportDefaultDeclaration, context) {
8892
- super(name, exportDefaultDeclaration, exportDefaultDeclaration.declaration, context, 'other');
9186
+ super(name, exportDefaultDeclaration, exportDefaultDeclaration.declaration, EMPTY_PATH, context, 'other');
8893
9187
  this.hasId = false;
8894
9188
  this.originalId = null;
8895
9189
  this.originalVariable = null;
@@ -9038,8 +9332,8 @@ class NamespaceVariable extends Variable {
9038
9332
  return (!memberVariable ||
9039
9333
  memberVariable.hasEffectsOnInteractionAtPath(path.slice(1), interaction, context));
9040
9334
  }
9041
- include() {
9042
- super.include();
9335
+ includePath(path, context) {
9336
+ super.includePath(path, context);
9043
9337
  this.context.includeAllExports();
9044
9338
  }
9045
9339
  prepare(accessedGlobalsByScope) {
@@ -9132,9 +9426,9 @@ class SyntheticNamedExportVariable extends Variable {
9132
9426
  getName(getPropertyAccess) {
9133
9427
  return `${this.syntheticNamespace.getName(getPropertyAccess)}${getPropertyAccess(this.name)}`;
9134
9428
  }
9135
- include() {
9136
- super.include();
9137
- this.context.includeVariableInModule(this.syntheticNamespace);
9429
+ includePath(path, context) {
9430
+ super.includePath(path, context);
9431
+ this.context.includeVariableInModule(this.syntheticNamespace, path, context);
9138
9432
  }
9139
9433
  setRenderNames(baseName, name) {
9140
9434
  super.setRenderNames(baseName, name);
@@ -12333,21 +12627,37 @@ class ArrayPattern extends NodeBase {
12333
12627
  element?.addExportedVariables(variables, exportNamesByVariable);
12334
12628
  }
12335
12629
  }
12336
- declare(kind) {
12630
+ declare(kind, destructuredInitPath, init) {
12337
12631
  const variables = [];
12632
+ const includedPatternPath = getIncludedPatternPath(destructuredInitPath);
12338
12633
  for (const element of this.elements) {
12339
12634
  if (element !== null) {
12340
- variables.push(...element.declare(kind, UNKNOWN_EXPRESSION));
12635
+ variables.push(...element.declare(kind, includedPatternPath, init));
12341
12636
  }
12342
12637
  }
12343
12638
  return variables;
12344
12639
  }
12640
+ deoptimizeAssignment(destructuredInitPath, init) {
12641
+ const includedPatternPath = getIncludedPatternPath(destructuredInitPath);
12642
+ for (const element of this.elements) {
12643
+ element?.deoptimizeAssignment(includedPatternPath, init);
12644
+ }
12645
+ }
12345
12646
  // Patterns can only be deoptimized at the empty path at the moment
12346
12647
  deoptimizePath() {
12347
12648
  for (const element of this.elements) {
12348
12649
  element?.deoptimizePath(EMPTY_PATH);
12349
12650
  }
12350
12651
  }
12652
+ hasEffectsWhenDestructuring(context, destructuredInitPath, init) {
12653
+ const includedPatternPath = getIncludedPatternPath(destructuredInitPath);
12654
+ for (const element of this.elements) {
12655
+ if (element?.hasEffectsWhenDestructuring(context, includedPatternPath, init)) {
12656
+ return true;
12657
+ }
12658
+ }
12659
+ return false;
12660
+ }
12351
12661
  // Patterns are only checked at the empty path at the moment
12352
12662
  hasEffectsOnInteractionAtPath(_path, interaction, context) {
12353
12663
  for (const element of this.elements) {
@@ -12356,12 +12666,38 @@ class ArrayPattern extends NodeBase {
12356
12666
  }
12357
12667
  return false;
12358
12668
  }
12669
+ includeDestructuredIfNecessary(context, destructuredInitPath, init) {
12670
+ let included = false;
12671
+ const includedPatternPath = getIncludedPatternPath(destructuredInitPath);
12672
+ for (const element of this.elements) {
12673
+ if (element) {
12674
+ element.included ||= included;
12675
+ included =
12676
+ element.includeDestructuredIfNecessary(context, includedPatternPath, init) || included;
12677
+ }
12678
+ }
12679
+ if (included) {
12680
+ // This is necessary so that if any pattern element is included, all are
12681
+ // included for proper deconflicting
12682
+ for (const element of this.elements) {
12683
+ if (element && !element.included) {
12684
+ element.included = true;
12685
+ element.includeDestructuredIfNecessary(context, includedPatternPath, init);
12686
+ }
12687
+ }
12688
+ }
12689
+ return (this.included ||= included);
12690
+ }
12359
12691
  markDeclarationReached() {
12360
12692
  for (const element of this.elements) {
12361
12693
  element?.markDeclarationReached();
12362
12694
  }
12363
12695
  }
12364
12696
  }
12697
+ ArrayPattern.prototype.includeNode = onlyIncludeSelf;
12698
+ const getIncludedPatternPath = (destructuredInitPath) => destructuredInitPath.at(-1) === UnknownKey
12699
+ ? destructuredInitPath
12700
+ : [...destructuredInitPath, UnknownInteger];
12365
12701
 
12366
12702
  class ArrowFunctionExpression extends FunctionBase {
12367
12703
  constructor() {
@@ -12378,8 +12714,6 @@ class ArrowFunctionExpression extends FunctionBase {
12378
12714
  this.scope = new ReturnValueScope(parentScope, false);
12379
12715
  }
12380
12716
  hasEffects() {
12381
- if (!this.deoptimized)
12382
- this.applyDeoptimizations();
12383
12717
  return false;
12384
12718
  }
12385
12719
  hasEffectsOnInteractionAtPath(path, interaction, context) {
@@ -12418,6 +12752,15 @@ class ArrowFunctionExpression extends FunctionBase {
12418
12752
  }
12419
12753
  }
12420
12754
  }
12755
+ includeNode(context) {
12756
+ this.included = true;
12757
+ this.body.includePath(UNKNOWN_PATH, context);
12758
+ for (const parameter of this.params) {
12759
+ if (!(parameter instanceof Identifier)) {
12760
+ parameter.includePath(UNKNOWN_PATH, context);
12761
+ }
12762
+ }
12763
+ }
12421
12764
  getObjectEntity() {
12422
12765
  if (this.objectEntity !== null) {
12423
12766
  return this.objectEntity;
@@ -12437,13 +12780,18 @@ class ObjectPattern extends NodeBase {
12437
12780
  }
12438
12781
  }
12439
12782
  }
12440
- declare(kind, init) {
12783
+ declare(kind, destructuredInitPath, init) {
12441
12784
  const variables = [];
12442
12785
  for (const property of this.properties) {
12443
- variables.push(...property.declare(kind, init));
12786
+ variables.push(...property.declare(kind, destructuredInitPath, init));
12444
12787
  }
12445
12788
  return variables;
12446
12789
  }
12790
+ deoptimizeAssignment(destructuredInitPath, init) {
12791
+ for (const property of this.properties) {
12792
+ property.deoptimizeAssignment(destructuredInitPath, init);
12793
+ }
12794
+ }
12447
12795
  deoptimizePath(path) {
12448
12796
  if (path.length === 0) {
12449
12797
  for (const property of this.properties) {
@@ -12461,12 +12809,46 @@ class ObjectPattern extends NodeBase {
12461
12809
  }
12462
12810
  return false;
12463
12811
  }
12812
+ hasEffectsWhenDestructuring(context, destructuredInitPath, init) {
12813
+ for (const property of this.properties) {
12814
+ if (property.hasEffectsWhenDestructuring(context, destructuredInitPath, init))
12815
+ return true;
12816
+ }
12817
+ return false;
12818
+ }
12819
+ includeDestructuredIfNecessary(context, destructuredInitPath, init) {
12820
+ let included = false;
12821
+ for (const property of this.properties) {
12822
+ included =
12823
+ property.includeDestructuredIfNecessary(context, destructuredInitPath, init) || included;
12824
+ }
12825
+ return (this.included ||= included);
12826
+ }
12464
12827
  markDeclarationReached() {
12465
12828
  for (const property of this.properties) {
12466
12829
  property.markDeclarationReached();
12467
12830
  }
12468
12831
  }
12832
+ render(code, options) {
12833
+ if (this.properties.length > 0) {
12834
+ const separatedNodes = getCommaSeparatedNodesWithBoundaries(this.properties, code, this.start + 1, this.end - 1);
12835
+ let lastSeparatorPos = null;
12836
+ for (const { node, separator, start, end } of separatedNodes) {
12837
+ if (!node.included) {
12838
+ treeshakeNode(node, code, start, end);
12839
+ continue;
12840
+ }
12841
+ lastSeparatorPos = separator;
12842
+ node.render(code, options);
12843
+ }
12844
+ if (lastSeparatorPos) {
12845
+ code.remove(lastSeparatorPos, this.end - 1);
12846
+ }
12847
+ }
12848
+ }
12469
12849
  }
12850
+ ObjectPattern.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
12851
+ ObjectPattern.prototype.applyDeoptimizations = doNotDeoptimize;
12470
12852
 
12471
12853
  class AssignmentExpression extends NodeBase {
12472
12854
  hasEffects(context) {
@@ -12475,7 +12857,9 @@ class AssignmentExpression extends NodeBase {
12475
12857
  this.applyDeoptimizations();
12476
12858
  // MemberExpressions do not access the property before assignments if the
12477
12859
  // operator is '='.
12478
- return (right.hasEffects(context) || left.hasEffectsAsAssignmentTarget(context, operator !== '='));
12860
+ return (right.hasEffects(context) ||
12861
+ left.hasEffectsAsAssignmentTarget(context, operator !== '=') ||
12862
+ this.left.hasEffectsWhenDestructuring?.(context, EMPTY_PATH, right));
12479
12863
  }
12480
12864
  hasEffectsOnInteractionAtPath(path, interaction, context) {
12481
12865
  return this.right.hasEffectsOnInteractionAtPath(path, interaction, context);
@@ -12484,15 +12868,24 @@ class AssignmentExpression extends NodeBase {
12484
12868
  const { deoptimized, left, right, operator } = this;
12485
12869
  if (!deoptimized)
12486
12870
  this.applyDeoptimizations();
12487
- this.included = true;
12871
+ if (!this.included)
12872
+ this.includeNode(context);
12873
+ const hasEffectsContext = createHasEffectsContext();
12488
12874
  if (includeChildrenRecursively ||
12489
12875
  operator !== '=' ||
12490
12876
  left.included ||
12491
- left.hasEffectsAsAssignmentTarget(createHasEffectsContext(), false)) {
12877
+ left.hasEffectsAsAssignmentTarget(hasEffectsContext, false) ||
12878
+ left.hasEffectsWhenDestructuring?.(hasEffectsContext, EMPTY_PATH, right)) {
12492
12879
  left.includeAsAssignmentTarget(context, includeChildrenRecursively, operator !== '=');
12493
12880
  }
12494
12881
  right.include(context, includeChildrenRecursively);
12495
12882
  }
12883
+ includeNode(context) {
12884
+ this.included = true;
12885
+ if (!this.deoptimized)
12886
+ this.applyDeoptimizations();
12887
+ this.right.includePath(UNKNOWN_PATH, context);
12888
+ }
12496
12889
  initialise() {
12497
12890
  super.initialise();
12498
12891
  if (this.left instanceof Identifier) {
@@ -12553,8 +12946,7 @@ class AssignmentExpression extends NodeBase {
12553
12946
  }
12554
12947
  applyDeoptimizations() {
12555
12948
  this.deoptimized = true;
12556
- this.left.deoptimizePath(EMPTY_PATH);
12557
- this.right.deoptimizePath(UNKNOWN_PATH);
12949
+ this.left.deoptimizeAssignment(EMPTY_PATH, this.right);
12558
12950
  this.scope.context.requestTreeshakingPass();
12559
12951
  }
12560
12952
  }
@@ -12563,8 +12955,11 @@ class AssignmentPattern extends NodeBase {
12563
12955
  addExportedVariables(variables, exportNamesByVariable) {
12564
12956
  this.left.addExportedVariables(variables, exportNamesByVariable);
12565
12957
  }
12566
- declare(kind, init) {
12567
- return this.left.declare(kind, init);
12958
+ declare(kind, destructuredInitPath, init) {
12959
+ return this.left.declare(kind, destructuredInitPath, init);
12960
+ }
12961
+ deoptimizeAssignment(destructuredInitPath, init) {
12962
+ this.left.deoptimizeAssignment(destructuredInitPath, init);
12568
12963
  }
12569
12964
  deoptimizePath(path) {
12570
12965
  if (path.length === 0) {
@@ -12574,6 +12969,29 @@ class AssignmentPattern extends NodeBase {
12574
12969
  hasEffectsOnInteractionAtPath(path, interaction, context) {
12575
12970
  return (path.length > 0 || this.left.hasEffectsOnInteractionAtPath(EMPTY_PATH, interaction, context));
12576
12971
  }
12972
+ hasEffectsWhenDestructuring(context, destructuredInitPath, init) {
12973
+ return this.left.hasEffectsWhenDestructuring(context, destructuredInitPath, init);
12974
+ }
12975
+ includeDestructuredIfNecessary(context, destructuredInitPath, init) {
12976
+ let included = this.left.includeDestructuredIfNecessary(context, destructuredInitPath, init) ||
12977
+ this.included;
12978
+ if ((included ||= this.right.shouldBeIncluded(context))) {
12979
+ this.right.include(context, false);
12980
+ if (!this.left.included) {
12981
+ this.left.included = true;
12982
+ // Unfortunately, we need to include the left side again now, so that
12983
+ // any declared variables are properly included.
12984
+ this.left.includeDestructuredIfNecessary(context, destructuredInitPath, init);
12985
+ }
12986
+ }
12987
+ return (this.included = included);
12988
+ }
12989
+ includeNode(context) {
12990
+ this.included = true;
12991
+ if (!this.deoptimized)
12992
+ this.applyDeoptimizations();
12993
+ this.right.includePath(UNKNOWN_PATH, context);
12994
+ }
12577
12995
  markDeclarationReached() {
12578
12996
  this.left.markDeclarationReached();
12579
12997
  }
@@ -12596,22 +13014,34 @@ class AwaitExpression extends NodeBase {
12596
13014
  return true;
12597
13015
  }
12598
13016
  include(context, includeChildrenRecursively) {
13017
+ if (!this.included)
13018
+ this.includeNode(context);
13019
+ this.argument.include(context, includeChildrenRecursively);
13020
+ }
13021
+ includeNode(context) {
13022
+ this.included = true;
12599
13023
  if (!this.deoptimized)
12600
13024
  this.applyDeoptimizations();
12601
- if (!this.included) {
12602
- this.included = true;
12603
- checkTopLevelAwait: if (!this.scope.context.usesTopLevelAwait) {
12604
- let parent = this.parent;
12605
- do {
12606
- if (parent instanceof FunctionNode || parent instanceof ArrowFunctionExpression)
12607
- break checkTopLevelAwait;
12608
- } while ((parent = parent.parent));
12609
- this.scope.context.usesTopLevelAwait = true;
12610
- }
13025
+ checkTopLevelAwait: if (!this.scope.context.usesTopLevelAwait) {
13026
+ let parent = this.parent;
13027
+ do {
13028
+ if (parent instanceof FunctionNode || parent instanceof ArrowFunctionExpression)
13029
+ break checkTopLevelAwait;
13030
+ } while ((parent = parent.parent));
13031
+ this.scope.context.usesTopLevelAwait = true;
12611
13032
  }
12612
- this.argument.include(context, includeChildrenRecursively);
13033
+ // Thenables need to be included
13034
+ this.argument.includePath(THEN_PATH, context);
13035
+ }
13036
+ includePath(path, context) {
13037
+ if (!this.deoptimized)
13038
+ this.applyDeoptimizations();
13039
+ if (!this.included)
13040
+ this.includeNode(context);
13041
+ this.argument.includePath(path, context);
12613
13042
  }
12614
13043
  }
13044
+ const THEN_PATH = ['then'];
12615
13045
 
12616
13046
  const binaryOperators = {
12617
13047
  '!=': (left, right) => left != right,
@@ -12675,6 +13105,8 @@ class BinaryExpression extends NodeBase {
12675
13105
  this.right.render(code, options);
12676
13106
  }
12677
13107
  }
13108
+ BinaryExpression.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
13109
+ BinaryExpression.prototype.applyDeoptimizations = doNotDeoptimize;
12678
13110
 
12679
13111
  class BreakStatement extends NodeBase {
12680
13112
  hasEffects(context) {
@@ -12694,7 +13126,7 @@ class BreakStatement extends NodeBase {
12694
13126
  include(context) {
12695
13127
  this.included = true;
12696
13128
  if (this.label) {
12697
- this.label.include();
13129
+ this.label.include(context);
12698
13130
  context.includedLabels.add(this.label.name);
12699
13131
  }
12700
13132
  else {
@@ -12703,6 +13135,8 @@ class BreakStatement extends NodeBase {
12703
13135
  context.brokenFlow = true;
12704
13136
  }
12705
13137
  }
13138
+ BreakStatement.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
13139
+ BreakStatement.prototype.applyDeoptimizations = doNotDeoptimize;
12706
13140
 
12707
13141
  function renderCallArguments(code, options, node) {
12708
13142
  if (node.arguments.length > 0) {
@@ -12889,8 +13323,6 @@ class CallExpression extends CallExpressionBase {
12889
13323
  this.callee.hasEffectsOnInteractionAtPath(EMPTY_PATH, this.interaction, context)));
12890
13324
  }
12891
13325
  include(context, includeChildrenRecursively) {
12892
- if (!this.deoptimized)
12893
- this.applyDeoptimizations();
12894
13326
  if (includeChildrenRecursively) {
12895
13327
  super.include(context, includeChildrenRecursively);
12896
13328
  if (includeChildrenRecursively === INCLUDE_PARAMETERS &&
@@ -12900,10 +13332,26 @@ class CallExpression extends CallExpressionBase {
12900
13332
  }
12901
13333
  }
12902
13334
  else {
12903
- this.included = true;
12904
- this.callee.include(context, false);
13335
+ if (!this.included)
13336
+ this.includeNode(context);
13337
+ // If the callee is a member expression and does not have a variable, its
13338
+ // object will already be included via the first argument of the
13339
+ // interaction in includeCallArguments. Including it again can lead to
13340
+ // severe performance problems.
13341
+ if (this.callee instanceof MemberExpression && !this.callee.variable) {
13342
+ this.callee.property.include(context, false);
13343
+ }
13344
+ else {
13345
+ this.callee.include(context, false);
13346
+ }
13347
+ this.callee.includeCallArguments(context, this.interaction);
12905
13348
  }
12906
- this.callee.includeCallArguments(context, this.arguments);
13349
+ }
13350
+ includeNode(context) {
13351
+ this.included = true;
13352
+ if (!this.deoptimized)
13353
+ this.applyDeoptimizations();
13354
+ this.callee.includePath(UNKNOWN_PATH, context);
12907
13355
  }
12908
13356
  initialise() {
12909
13357
  super.initialise();
@@ -12942,13 +13390,14 @@ class CatchClause extends NodeBase {
12942
13390
  this.type = type;
12943
13391
  if (param) {
12944
13392
  this.param = new (this.scope.context.getNodeConstructor(param.type))(this, this.scope).parseNode(param);
12945
- this.param.declare('parameter', UNKNOWN_EXPRESSION);
13393
+ this.param.declare('parameter', EMPTY_PATH, UNKNOWN_EXPRESSION);
12946
13394
  }
12947
13395
  this.body = new BlockStatement(this, this.scope.bodyScope).parseNode(body);
12948
13396
  return super.parseNode(esTreeNode);
12949
13397
  }
12950
13398
  }
12951
13399
  CatchClause.prototype.preventChildBlockScope = true;
13400
+ CatchClause.prototype.includeNode = onlyIncludeSelf;
12952
13401
 
12953
13402
  class ChainExpression extends NodeBase {
12954
13403
  // deoptimizations are not relevant as we are not caching values
@@ -12960,17 +13409,22 @@ class ChainExpression extends NodeBase {
12960
13409
  hasEffects(context) {
12961
13410
  return this.expression.hasEffectsAsChainElement(context) === true;
12962
13411
  }
13412
+ includePath(path, context) {
13413
+ this.included = true;
13414
+ this.expression.includePath(path, context);
13415
+ }
12963
13416
  removeAnnotations(code) {
12964
13417
  this.expression.removeAnnotations(code);
12965
13418
  }
12966
- applyDeoptimizations() { }
12967
13419
  }
13420
+ ChainExpression.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
13421
+ ChainExpression.prototype.applyDeoptimizations = doNotDeoptimize;
12968
13422
 
12969
13423
  class ClassBodyScope extends ChildScope {
12970
13424
  constructor(parent, classNode) {
12971
13425
  const { context } = parent;
12972
13426
  super(parent, context);
12973
- this.variables.set('this', (this.thisVariable = new LocalVariable('this', null, classNode, context, 'other')));
13427
+ this.variables.set('this', (this.thisVariable = new LocalVariable('this', null, classNode, EMPTY_PATH, context, 'other')));
12974
13428
  this.instanceScope = new ChildScope(this, context);
12975
13429
  this.instanceScope.variables.set('this', new ThisVariable(context));
12976
13430
  }
@@ -12985,7 +13439,7 @@ class ClassBody extends NodeBase {
12985
13439
  }
12986
13440
  include(context, includeChildrenRecursively) {
12987
13441
  this.included = true;
12988
- this.scope.context.includeVariableInModule(this.scope.thisVariable);
13442
+ this.scope.context.includeVariableInModule(this.scope.thisVariable, UNKNOWN_PATH, context);
12989
13443
  for (const definition of this.body) {
12990
13444
  definition.include(context, includeChildrenRecursively);
12991
13445
  }
@@ -12998,8 +13452,9 @@ class ClassBody extends NodeBase {
12998
13452
  }
12999
13453
  return super.parseNode(esTreeNode);
13000
13454
  }
13001
- applyDeoptimizations() { }
13002
13455
  }
13456
+ ClassBody.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
13457
+ ClassBody.prototype.applyDeoptimizations = doNotDeoptimize;
13003
13458
 
13004
13459
  class ClassExpression extends ClassNode {
13005
13460
  render(code, options, { renderedSurroundingElement } = parseAst_js.BLANK) {
@@ -13057,6 +13512,9 @@ class ConditionalExpression extends NodeBase {
13057
13512
  const unusedBranch = this.usedBranch === this.consequent ? this.alternate : this.consequent;
13058
13513
  this.usedBranch = null;
13059
13514
  unusedBranch.deoptimizePath(UNKNOWN_PATH);
13515
+ if (this.included) {
13516
+ unusedBranch.includePath(UNKNOWN_PATH, createInclusionContext());
13517
+ }
13060
13518
  const { expressionsToBeDeoptimized } = this;
13061
13519
  this.expressionsToBeDeoptimized = parseAst_js.EMPTY_ARRAY;
13062
13520
  for (const expression of expressionsToBeDeoptimized) {
@@ -13114,7 +13572,7 @@ class ConditionalExpression extends NodeBase {
13114
13572
  include(context, includeChildrenRecursively) {
13115
13573
  this.included = true;
13116
13574
  const usedBranch = this.getUsedBranch();
13117
- if (includeChildrenRecursively || this.test.shouldBeIncluded(context) || usedBranch === null) {
13575
+ if (usedBranch === null || includeChildrenRecursively || this.test.shouldBeIncluded(context)) {
13118
13576
  this.test.include(context, includeChildrenRecursively);
13119
13577
  this.consequent.include(context, includeChildrenRecursively);
13120
13578
  this.alternate.include(context, includeChildrenRecursively);
@@ -13123,27 +13581,38 @@ class ConditionalExpression extends NodeBase {
13123
13581
  usedBranch.include(context, includeChildrenRecursively);
13124
13582
  }
13125
13583
  }
13126
- includeCallArguments(context, parameters) {
13584
+ includePath(path, context) {
13585
+ this.included = true;
13586
+ const usedBranch = this.getUsedBranch();
13587
+ if (usedBranch === null || this.test.shouldBeIncluded(context)) {
13588
+ this.consequent.includePath(path, context);
13589
+ this.alternate.includePath(path, context);
13590
+ }
13591
+ else {
13592
+ usedBranch.includePath(path, context);
13593
+ }
13594
+ }
13595
+ includeCallArguments(context, interaction) {
13127
13596
  const usedBranch = this.getUsedBranch();
13128
13597
  if (usedBranch) {
13129
- usedBranch.includeCallArguments(context, parameters);
13598
+ usedBranch.includeCallArguments(context, interaction);
13130
13599
  }
13131
13600
  else {
13132
- this.consequent.includeCallArguments(context, parameters);
13133
- this.alternate.includeCallArguments(context, parameters);
13601
+ this.consequent.includeCallArguments(context, interaction);
13602
+ this.alternate.includeCallArguments(context, interaction);
13134
13603
  }
13135
13604
  }
13136
13605
  removeAnnotations(code) {
13137
13606
  this.test.removeAnnotations(code);
13138
13607
  }
13139
13608
  render(code, options, { isCalleeOfRenderedParent, preventASI, renderedParentType, renderedSurroundingElement } = parseAst_js.BLANK) {
13140
- const usedBranch = this.getUsedBranch();
13141
13609
  if (this.test.included) {
13142
13610
  this.test.render(code, options, { renderedSurroundingElement });
13143
13611
  this.consequent.render(code, options);
13144
13612
  this.alternate.render(code, options);
13145
13613
  }
13146
13614
  else {
13615
+ const usedBranch = this.getUsedBranch();
13147
13616
  const colonPos = findFirstOccurrenceOutsideComment(code.original, ':', this.consequent.end);
13148
13617
  const inclusionStart = findNonWhiteSpace(code.original, (this.consequent.included
13149
13618
  ? findFirstOccurrenceOutsideComment(code.original, '?', this.test.end)
@@ -13175,6 +13644,8 @@ class ConditionalExpression extends NodeBase {
13175
13644
  : (this.usedBranch = testValue ? this.consequent : this.alternate);
13176
13645
  }
13177
13646
  }
13647
+ ConditionalExpression.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
13648
+ ConditionalExpression.prototype.applyDeoptimizations = doNotDeoptimize;
13178
13649
 
13179
13650
  class ContinueStatement extends NodeBase {
13180
13651
  hasEffects(context) {
@@ -13194,7 +13665,7 @@ class ContinueStatement extends NodeBase {
13194
13665
  include(context) {
13195
13666
  this.included = true;
13196
13667
  if (this.label) {
13197
- this.label.include();
13668
+ this.label.include(context);
13198
13669
  context.includedLabels.add(this.label.name);
13199
13670
  }
13200
13671
  else {
@@ -13203,12 +13674,15 @@ class ContinueStatement extends NodeBase {
13203
13674
  context.brokenFlow = true;
13204
13675
  }
13205
13676
  }
13677
+ ContinueStatement.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
13678
+ ContinueStatement.prototype.applyDeoptimizations = doNotDeoptimize;
13206
13679
 
13207
13680
  class DebuggerStatement extends NodeBase {
13208
13681
  hasEffects() {
13209
13682
  return true;
13210
13683
  }
13211
13684
  }
13685
+ DebuggerStatement.prototype.includeNode = onlyIncludeSelf;
13212
13686
 
13213
13687
  class Decorator extends NodeBase {
13214
13688
  hasEffects(context) {
@@ -13216,6 +13690,7 @@ class Decorator extends NodeBase {
13216
13690
  this.expression.hasEffectsOnInteractionAtPath(EMPTY_PATH, NODE_INTERACTION_UNKNOWN_CALL, context));
13217
13691
  }
13218
13692
  }
13693
+ Decorator.prototype.includeNode = onlyIncludeSelf;
13219
13694
 
13220
13695
  function hasLoopBodyEffects(context, body) {
13221
13696
  const { brokenFlow, hasBreak, hasContinue, ignore } = context;
@@ -13255,12 +13730,15 @@ class DoWhileStatement extends NodeBase {
13255
13730
  includeLoopBody(context, this.body, includeChildrenRecursively);
13256
13731
  }
13257
13732
  }
13733
+ DoWhileStatement.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
13734
+ DoWhileStatement.prototype.applyDeoptimizations = doNotDeoptimize;
13258
13735
 
13259
13736
  class EmptyStatement extends NodeBase {
13260
13737
  hasEffects() {
13261
13738
  return false;
13262
13739
  }
13263
13740
  }
13741
+ EmptyStatement.prototype.includeNode = onlyIncludeSelf;
13264
13742
 
13265
13743
  class ExportAllDeclaration extends NodeBase {
13266
13744
  hasEffects() {
@@ -13273,9 +13751,10 @@ class ExportAllDeclaration extends NodeBase {
13273
13751
  render(code, _options, nodeRenderOptions) {
13274
13752
  code.remove(nodeRenderOptions.start, nodeRenderOptions.end);
13275
13753
  }
13276
- applyDeoptimizations() { }
13277
13754
  }
13278
13755
  ExportAllDeclaration.prototype.needsBoundaries = true;
13756
+ ExportAllDeclaration.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
13757
+ ExportAllDeclaration.prototype.applyDeoptimizations = doNotDeoptimize;
13279
13758
 
13280
13759
  class ExportNamedDeclaration extends NodeBase {
13281
13760
  bind() {
@@ -13302,13 +13781,15 @@ class ExportNamedDeclaration extends NodeBase {
13302
13781
  this.declaration.render(code, options, { end, start });
13303
13782
  }
13304
13783
  }
13305
- applyDeoptimizations() { }
13306
13784
  }
13307
13785
  ExportNamedDeclaration.prototype.needsBoundaries = true;
13786
+ ExportNamedDeclaration.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
13787
+ ExportNamedDeclaration.prototype.applyDeoptimizations = doNotDeoptimize;
13308
13788
 
13309
13789
  class ExportSpecifier extends NodeBase {
13310
- applyDeoptimizations() { }
13311
13790
  }
13791
+ ExportSpecifier.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
13792
+ ExportSpecifier.prototype.applyDeoptimizations = doNotDeoptimize;
13312
13793
 
13313
13794
  class ForInStatement extends NodeBase {
13314
13795
  createScope(parentScope) {
@@ -13326,11 +13807,18 @@ class ForInStatement extends NodeBase {
13326
13807
  const { body, deoptimized, left, right } = this;
13327
13808
  if (!deoptimized)
13328
13809
  this.applyDeoptimizations();
13329
- this.included = true;
13810
+ if (!this.included)
13811
+ this.includeNode(context);
13330
13812
  left.includeAsAssignmentTarget(context, includeChildrenRecursively || true, false);
13331
13813
  right.include(context, includeChildrenRecursively);
13332
13814
  includeLoopBody(context, body, includeChildrenRecursively);
13333
13815
  }
13816
+ includeNode(context) {
13817
+ this.included = true;
13818
+ if (!this.deoptimized)
13819
+ this.applyDeoptimizations();
13820
+ this.right.includePath(UNKNOWN_PATH, context);
13821
+ }
13334
13822
  initialise() {
13335
13823
  super.initialise();
13336
13824
  this.left.setAssignedValue(UNKNOWN_EXPRESSION);
@@ -13371,11 +13859,18 @@ class ForOfStatement extends NodeBase {
13371
13859
  const { body, deoptimized, left, right } = this;
13372
13860
  if (!deoptimized)
13373
13861
  this.applyDeoptimizations();
13374
- this.included = true;
13862
+ if (!this.included)
13863
+ this.includeNode(context);
13375
13864
  left.includeAsAssignmentTarget(context, includeChildrenRecursively || true, false);
13376
13865
  right.include(context, includeChildrenRecursively);
13377
13866
  includeLoopBody(context, body, includeChildrenRecursively);
13378
13867
  }
13868
+ includeNode(context) {
13869
+ this.included = true;
13870
+ if (!this.deoptimized)
13871
+ this.applyDeoptimizations();
13872
+ this.right.includePath(UNKNOWN_PATH, context);
13873
+ }
13379
13874
  initialise() {
13380
13875
  super.initialise();
13381
13876
  this.left.setAssignedValue(UNKNOWN_EXPRESSION);
@@ -13411,7 +13906,9 @@ class ForStatement extends NodeBase {
13411
13906
  }
13412
13907
  include(context, includeChildrenRecursively) {
13413
13908
  this.included = true;
13414
- this.init?.include(context, includeChildrenRecursively, { asSingleStatement: true });
13909
+ this.init?.include(context, includeChildrenRecursively, {
13910
+ asSingleStatement: true
13911
+ });
13415
13912
  this.test?.include(context, includeChildrenRecursively);
13416
13913
  this.update?.include(context, includeChildrenRecursively);
13417
13914
  includeLoopBody(context, this.body, includeChildrenRecursively);
@@ -13423,6 +13920,8 @@ class ForStatement extends NodeBase {
13423
13920
  this.body.render(code, options);
13424
13921
  }
13425
13922
  }
13923
+ ForStatement.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
13924
+ ForStatement.prototype.applyDeoptimizations = doNotDeoptimize;
13426
13925
 
13427
13926
  class FunctionExpression extends FunctionNode {
13428
13927
  createScope(parentScope) {
@@ -13454,9 +13953,9 @@ class TrackingScope extends BlockScope {
13454
13953
  super(...arguments);
13455
13954
  this.hoistedDeclarations = [];
13456
13955
  }
13457
- addDeclaration(identifier, context, init, kind) {
13956
+ addDeclaration(identifier, context, init, destructuredInitPath, kind) {
13458
13957
  this.hoistedDeclarations.push(identifier);
13459
- return super.addDeclaration(identifier, context, init, kind);
13958
+ return super.addDeclaration(identifier, context, init, destructuredInitPath, kind);
13460
13959
  }
13461
13960
  }
13462
13961
 
@@ -13555,7 +14054,6 @@ class IfStatement extends NodeBase {
13555
14054
  }
13556
14055
  this.renderHoistedDeclarations(hoistedDeclarations, code, getPropertyAccess);
13557
14056
  }
13558
- applyDeoptimizations() { }
13559
14057
  getTestValue() {
13560
14058
  if (this.testValue === unset) {
13561
14059
  return (this.testValue = this.test.getLiteralValueAtPath(EMPTY_PATH, SHARED_RECURSION_TRACKER, this));
@@ -13624,6 +14122,8 @@ class IfStatement extends NodeBase {
13624
14122
  return false;
13625
14123
  }
13626
14124
  }
14125
+ IfStatement.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
14126
+ IfStatement.prototype.applyDeoptimizations = doNotDeoptimize;
13627
14127
 
13628
14128
  class ImportAttribute extends NodeBase {
13629
14129
  }
@@ -13641,13 +14141,15 @@ class ImportDeclaration extends NodeBase {
13641
14141
  render(code, _options, nodeRenderOptions) {
13642
14142
  code.remove(nodeRenderOptions.start, nodeRenderOptions.end);
13643
14143
  }
13644
- applyDeoptimizations() { }
13645
14144
  }
13646
14145
  ImportDeclaration.prototype.needsBoundaries = true;
14146
+ ImportDeclaration.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
14147
+ ImportDeclaration.prototype.applyDeoptimizations = doNotDeoptimize;
13647
14148
 
13648
14149
  class ImportDefaultSpecifier extends NodeBase {
13649
- applyDeoptimizations() { }
13650
14150
  }
14151
+ ImportDefaultSpecifier.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
14152
+ ImportDefaultSpecifier.prototype.applyDeoptimizations = doNotDeoptimize;
13651
14153
 
13652
14154
  function isReassignedExportsMember(variable, exportNamesByVariable) {
13653
14155
  return (variable.renderBaseName !== null && exportNamesByVariable.has(variable) && variable.isReassigned);
@@ -13656,28 +14158,33 @@ function isReassignedExportsMember(variable, exportNamesByVariable) {
13656
14158
  class VariableDeclarator extends NodeBase {
13657
14159
  declareDeclarator(kind, isUsingDeclaration) {
13658
14160
  this.isUsingDeclaration = isUsingDeclaration;
13659
- this.id.declare(kind, this.init || UNDEFINED_EXPRESSION);
14161
+ this.id.declare(kind, EMPTY_PATH, this.init || UNDEFINED_EXPRESSION);
13660
14162
  }
13661
14163
  deoptimizePath(path) {
13662
14164
  this.id.deoptimizePath(path);
13663
14165
  }
13664
14166
  hasEffects(context) {
13665
- if (!this.deoptimized)
13666
- this.applyDeoptimizations();
13667
14167
  const initEffect = this.init?.hasEffects(context);
13668
14168
  this.id.markDeclarationReached();
13669
- return initEffect || this.id.hasEffects(context) || this.isUsingDeclaration;
14169
+ return (initEffect ||
14170
+ this.isUsingDeclaration ||
14171
+ this.id.hasEffects(context) ||
14172
+ (this.scope.context.options.treeshake
14173
+ .propertyReadSideEffects &&
14174
+ this.id.hasEffectsWhenDestructuring(context, EMPTY_PATH, this.init || UNDEFINED_EXPRESSION)));
13670
14175
  }
13671
14176
  include(context, includeChildrenRecursively) {
13672
- const { deoptimized, id, init } = this;
13673
- if (!deoptimized)
13674
- this.applyDeoptimizations();
13675
- this.included = true;
14177
+ const { id, init } = this;
14178
+ if (!this.included)
14179
+ this.includeNode();
13676
14180
  init?.include(context, includeChildrenRecursively);
13677
14181
  id.markDeclarationReached();
13678
- if (includeChildrenRecursively || id.shouldBeIncluded(context)) {
14182
+ if (includeChildrenRecursively) {
13679
14183
  id.include(context, includeChildrenRecursively);
13680
14184
  }
14185
+ else {
14186
+ id.includeDestructuredIfNecessary(context, EMPTY_PATH, init || UNDEFINED_EXPRESSION);
14187
+ }
13681
14188
  }
13682
14189
  removeAnnotations(code) {
13683
14190
  this.init?.removeAnnotations(code);
@@ -13707,8 +14214,8 @@ class VariableDeclarator extends NodeBase {
13707
14214
  code.appendLeft(end, `${_}=${_}void 0`);
13708
14215
  }
13709
14216
  }
13710
- applyDeoptimizations() {
13711
- this.deoptimized = true;
14217
+ includeNode() {
14218
+ this.included = true;
13712
14219
  const { id, init } = this;
13713
14220
  if (init && id instanceof Identifier && init instanceof ClassExpression && !init.id) {
13714
14221
  const { name, variable } = id;
@@ -13720,11 +14227,14 @@ class VariableDeclarator extends NodeBase {
13720
14227
  }
13721
14228
  }
13722
14229
  }
14230
+ VariableDeclarator.prototype.applyDeoptimizations = doNotDeoptimize;
13723
14231
 
13724
14232
  class ImportExpression extends NodeBase {
13725
14233
  constructor() {
13726
14234
  super(...arguments);
13727
14235
  this.inlineNamespace = null;
14236
+ this.hasUnknownAccessedKey = false;
14237
+ this.accessedPropKey = new Set();
13728
14238
  this.attributes = null;
13729
14239
  this.mechanism = null;
13730
14240
  this.namespaceExportName = undefined;
@@ -13757,12 +14267,15 @@ class ImportExpression extends NodeBase {
13757
14267
  if (parent2 instanceof ExpressionStatement) {
13758
14268
  return parseAst_js.EMPTY_ARRAY;
13759
14269
  }
13760
- // Case 1: const { foo } = await import('bar')
14270
+ // Case 1: const { foo } / module = await import('bar')
13761
14271
  if (parent2 instanceof VariableDeclarator) {
13762
14272
  const declaration = parent2.id;
13763
- return declaration instanceof ObjectPattern
13764
- ? getDeterministicObjectDestructure(declaration)
13765
- : undefined;
14273
+ if (declaration instanceof Identifier) {
14274
+ return this.hasUnknownAccessedKey ? undefined : [...this.accessedPropKey];
14275
+ }
14276
+ if (declaration instanceof ObjectPattern) {
14277
+ return getDeterministicObjectDestructure(declaration);
14278
+ }
13766
14279
  }
13767
14280
  // Case 2: (await import('bar')).foo
13768
14281
  if (parent2 instanceof MemberExpression) {
@@ -13812,13 +14325,30 @@ class ImportExpression extends NodeBase {
13812
14325
  return true;
13813
14326
  }
13814
14327
  include(context, includeChildrenRecursively) {
13815
- if (!this.included) {
13816
- this.included = true;
13817
- this.scope.context.includeDynamicImport(this);
13818
- this.scope.addAccessedDynamicImport(this);
13819
- }
14328
+ if (!this.included)
14329
+ this.includeNode();
13820
14330
  this.source.include(context, includeChildrenRecursively);
13821
14331
  }
14332
+ includeNode() {
14333
+ this.included = true;
14334
+ this.scope.context.includeDynamicImport(this);
14335
+ this.scope.addAccessedDynamicImport(this);
14336
+ }
14337
+ includePath(path) {
14338
+ if (!this.included)
14339
+ this.includeNode();
14340
+ // Technically, this is not correct as dynamic imports return a Promise.
14341
+ if (this.hasUnknownAccessedKey)
14342
+ return;
14343
+ if (path[0] === UnknownKey) {
14344
+ this.hasUnknownAccessedKey = true;
14345
+ }
14346
+ else if (typeof path[0] === 'string') {
14347
+ this.accessedPropKey.add(path[0]);
14348
+ }
14349
+ // Update included paths
14350
+ this.scope.context.includeDynamicImport(this);
14351
+ }
13822
14352
  initialise() {
13823
14353
  super.initialise();
13824
14354
  this.scope.context.addDynamicImport(this);
@@ -13887,7 +14417,6 @@ class ImportExpression extends NodeBase {
13887
14417
  setInternalResolution(inlineNamespace) {
13888
14418
  this.inlineNamespace = inlineNamespace;
13889
14419
  }
13890
- applyDeoptimizations() { }
13891
14420
  getDynamicImportMechanismAndHelper(resolution, exportMode, { compact, dynamicImportInCjs, format, generatedCode: { arrowFunctions }, interop }, { _, getDirectReturnFunction, getDirectReturnIifeLeft }, pluginDriver) {
13892
14421
  const mechanism = pluginDriver.hookFirstSync('renderDynamicImport', [
13893
14422
  {
@@ -13977,6 +14506,7 @@ class ImportExpression extends NodeBase {
13977
14506
  return { helper: null, mechanism: null };
13978
14507
  }
13979
14508
  }
14509
+ ImportExpression.prototype.applyDeoptimizations = doNotDeoptimize;
13980
14510
  function getInteropHelper(resolution, exportMode, interop) {
13981
14511
  return exportMode === 'external'
13982
14512
  ? namespaceInteropHelpersByInteropType[interop(resolution instanceof ExternalModule ? resolution.id : null)]
@@ -14000,12 +14530,14 @@ function getDeterministicObjectDestructure(objectPattern) {
14000
14530
  }
14001
14531
 
14002
14532
  class ImportNamespaceSpecifier extends NodeBase {
14003
- applyDeoptimizations() { }
14004
14533
  }
14534
+ ImportNamespaceSpecifier.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
14535
+ ImportNamespaceSpecifier.prototype.applyDeoptimizations = doNotDeoptimize;
14005
14536
 
14006
14537
  class ImportSpecifier extends NodeBase {
14007
- applyDeoptimizations() { }
14008
14538
  }
14539
+ ImportSpecifier.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
14540
+ ImportSpecifier.prototype.applyDeoptimizations = doNotDeoptimize;
14009
14541
 
14010
14542
  class JSXIdentifier extends IdentifierBase {
14011
14543
  constructor() {
@@ -14022,6 +14554,29 @@ class JSXIdentifier extends IdentifierBase {
14022
14554
  this.isNativeElement = true;
14023
14555
  }
14024
14556
  }
14557
+ include(context) {
14558
+ if (!this.included)
14559
+ this.includeNode(context);
14560
+ }
14561
+ includeNode(context) {
14562
+ this.included = true;
14563
+ if (!this.deoptimized)
14564
+ this.applyDeoptimizations();
14565
+ if (this.variable !== null) {
14566
+ this.scope.context.includeVariableInModule(this.variable, EMPTY_PATH, context);
14567
+ }
14568
+ }
14569
+ includePath(path, context) {
14570
+ if (!this.included) {
14571
+ this.included = true;
14572
+ if (this.variable !== null) {
14573
+ this.scope.context.includeVariableInModule(this.variable, path, context);
14574
+ }
14575
+ }
14576
+ else if (path.length > 0) {
14577
+ this.variable?.includePath(path, context);
14578
+ }
14579
+ }
14025
14580
  render(code, { snippets: { getPropertyAccess }, useOriginalName }) {
14026
14581
  if (this.variable) {
14027
14582
  const name = this.variable.getName(getPropertyAccess, useOriginalName);
@@ -14083,6 +14638,7 @@ class JSXAttribute extends NodeBase {
14083
14638
  }
14084
14639
  }
14085
14640
  }
14641
+ JSXAttribute.prototype.includeNode = onlyIncludeSelf;
14086
14642
 
14087
14643
  class JSXClosingBase extends NodeBase {
14088
14644
  render(code, options) {
@@ -14095,6 +14651,7 @@ class JSXClosingBase extends NodeBase {
14095
14651
  }
14096
14652
  }
14097
14653
  }
14654
+ JSXClosingBase.prototype.includeNode = onlyIncludeSelf;
14098
14655
 
14099
14656
  class JSXClosingElement extends JSXClosingBase {
14100
14657
  }
@@ -14115,8 +14672,15 @@ class JSXSpreadAttribute extends NodeBase {
14115
14672
 
14116
14673
  class JSXEmptyExpression extends NodeBase {
14117
14674
  }
14675
+ JSXEmptyExpression.prototype.includeNode = onlyIncludeSelf;
14118
14676
 
14119
14677
  class JSXExpressionContainer extends NodeBase {
14678
+ includeNode(context) {
14679
+ this.included = true;
14680
+ if (!this.deoptimized)
14681
+ this.applyDeoptimizations();
14682
+ this.expression.includePath(UNKNOWN_PATH, context);
14683
+ }
14120
14684
  render(code, options) {
14121
14685
  const { mode } = this.scope.context.options.jsx;
14122
14686
  if (mode !== 'preserve') {
@@ -14137,7 +14701,7 @@ function getRenderedJsxChildren(children) {
14137
14701
  return renderedChildren;
14138
14702
  }
14139
14703
 
14140
- function getAndIncludeFactoryVariable(factory, preserve, importSource, node) {
14704
+ function getAndIncludeFactoryVariable(factory, preserve, importSource, node, context) {
14141
14705
  const [baseName, nestedName] = factory.split('.');
14142
14706
  let factoryVariable;
14143
14707
  if (importSource) {
@@ -14145,7 +14709,7 @@ function getAndIncludeFactoryVariable(factory, preserve, importSource, node) {
14145
14709
  if (preserve) {
14146
14710
  // This pretends we are accessing an included global variable of the same name
14147
14711
  const globalVariable = node.scope.findGlobal(baseName);
14148
- globalVariable.include();
14712
+ globalVariable.includePath(UNKNOWN_PATH, context);
14149
14713
  // This excludes this variable from renaming
14150
14714
  factoryVariable.globalName = baseName;
14151
14715
  }
@@ -14153,7 +14717,7 @@ function getAndIncludeFactoryVariable(factory, preserve, importSource, node) {
14153
14717
  else {
14154
14718
  factoryVariable = node.scope.findGlobal(baseName);
14155
14719
  }
14156
- node.scope.context.includeVariableInModule(factoryVariable);
14720
+ node.scope.context.includeVariableInModule(factoryVariable, UNKNOWN_PATH, context);
14157
14721
  if (factoryVariable instanceof LocalVariable) {
14158
14722
  factoryVariable.consolidateInitializers();
14159
14723
  factoryVariable.addUsedPlace(node);
@@ -14176,16 +14740,20 @@ class JSXElementBase extends NodeBase {
14176
14740
  }
14177
14741
  }
14178
14742
  include(context, includeChildrenRecursively) {
14179
- if (!this.included) {
14180
- const { factory, importSource, mode } = this.jsxMode;
14181
- if (factory) {
14182
- this.factory = factory;
14183
- this.factoryVariable = getAndIncludeFactoryVariable(factory, mode === 'preserve', importSource, this);
14184
- }
14743
+ if (!this.included)
14744
+ this.includeNode(context);
14745
+ for (const child of this.children) {
14746
+ child.include(context, includeChildrenRecursively);
14747
+ }
14748
+ }
14749
+ includeNode(context) {
14750
+ this.included = true;
14751
+ const { factory, importSource, mode } = this.jsxMode;
14752
+ if (factory) {
14753
+ this.factory = factory;
14754
+ this.factoryVariable = getAndIncludeFactoryVariable(factory, mode === 'preserve', importSource, this, context);
14185
14755
  }
14186
- super.include(context, includeChildrenRecursively);
14187
14756
  }
14188
- applyDeoptimizations() { }
14189
14757
  getRenderingMode() {
14190
14758
  const jsx = this.scope.context.options.jsx;
14191
14759
  const { mode, factory, importSource } = jsx;
@@ -14223,8 +14791,14 @@ class JSXElementBase extends NodeBase {
14223
14791
  return { childrenEnd, firstChild, hasMultipleChildren };
14224
14792
  }
14225
14793
  }
14794
+ JSXElementBase.prototype.applyDeoptimizations = doNotDeoptimize;
14226
14795
 
14227
14796
  class JSXElement extends JSXElementBase {
14797
+ include(context, includeChildrenRecursively) {
14798
+ super.include(context, includeChildrenRecursively);
14799
+ this.openingElement.include(context, includeChildrenRecursively);
14800
+ this.closingElement?.include(context, includeChildrenRecursively);
14801
+ }
14228
14802
  render(code, options) {
14229
14803
  switch (this.jsxMode.mode) {
14230
14804
  case 'classic': {
@@ -14376,6 +14950,11 @@ class JSXElement extends JSXElementBase {
14376
14950
  }
14377
14951
 
14378
14952
  class JSXFragment extends JSXElementBase {
14953
+ include(context, includeChildrenRecursively) {
14954
+ super.include(context, includeChildrenRecursively);
14955
+ this.openingFragment.include(context, includeChildrenRecursively);
14956
+ this.closingFragment.include(context, includeChildrenRecursively);
14957
+ }
14379
14958
  render(code, options) {
14380
14959
  switch (this.jsxMode.mode) {
14381
14960
  case 'classic': {
@@ -14425,10 +15004,22 @@ class JSXFragment extends JSXElementBase {
14425
15004
  }
14426
15005
 
14427
15006
  class JSXMemberExpression extends NodeBase {
15007
+ includeNode(context) {
15008
+ this.included = true;
15009
+ if (!this.deoptimized)
15010
+ this.applyDeoptimizations();
15011
+ this.object.includePath([this.property.name], context);
15012
+ }
15013
+ includePath(path, context) {
15014
+ if (!this.included)
15015
+ this.includeNode(context);
15016
+ this.object.includePath([this.property.name, ...path], context);
15017
+ }
14428
15018
  }
14429
15019
 
14430
15020
  class JSXNamespacedName extends NodeBase {
14431
15021
  }
15022
+ JSXNamespacedName.prototype.includeNode = onlyIncludeSelf;
14432
15023
 
14433
15024
  class JSXOpeningElement extends NodeBase {
14434
15025
  render(code, options, { jsxMode = this.scope.context.options.jsx.mode } = {}) {
@@ -14438,6 +15029,7 @@ class JSXOpeningElement extends NodeBase {
14438
15029
  }
14439
15030
  }
14440
15031
  }
15032
+ JSXOpeningElement.prototype.includeNode = onlyIncludeSelf;
14441
15033
 
14442
15034
  class JSXOpeningFragment extends NodeBase {
14443
15035
  constructor() {
@@ -14445,22 +15037,22 @@ class JSXOpeningFragment extends NodeBase {
14445
15037
  this.fragment = null;
14446
15038
  this.fragmentVariable = null;
14447
15039
  }
14448
- include(context, includeChildrenRecursively) {
14449
- if (!this.included) {
14450
- const jsx = this.scope.context.options.jsx;
14451
- if (jsx.mode === 'automatic') {
14452
- this.fragment = 'Fragment';
14453
- this.fragmentVariable = getAndIncludeFactoryVariable('Fragment', false, jsx.jsxImportSource, this);
14454
- }
14455
- else {
14456
- const { fragment, importSource, mode } = jsx;
14457
- if (fragment != null) {
14458
- this.fragment = fragment;
14459
- this.fragmentVariable = getAndIncludeFactoryVariable(fragment, mode === 'preserve', importSource, this);
14460
- }
15040
+ includeNode(context) {
15041
+ this.included = true;
15042
+ if (!this.deoptimized)
15043
+ this.applyDeoptimizations();
15044
+ const jsx = this.scope.context.options.jsx;
15045
+ if (jsx.mode === 'automatic') {
15046
+ this.fragment = 'Fragment';
15047
+ this.fragmentVariable = getAndIncludeFactoryVariable('Fragment', false, jsx.jsxImportSource, this, context);
15048
+ }
15049
+ else {
15050
+ const { fragment, importSource, mode } = jsx;
15051
+ if (fragment != null) {
15052
+ this.fragment = fragment;
15053
+ this.fragmentVariable = getAndIncludeFactoryVariable(fragment, mode === 'preserve', importSource, this, context);
14461
15054
  }
14462
15055
  }
14463
- super.include(context, includeChildrenRecursively);
14464
15056
  }
14465
15057
  render(code, options) {
14466
15058
  const { mode } = this.scope.context.options.jsx;
@@ -14497,6 +15089,7 @@ class JSXText extends NodeBase {
14497
15089
  }
14498
15090
  }
14499
15091
  }
15092
+ JSXText.prototype.includeNode = onlyIncludeSelf;
14500
15093
 
14501
15094
  class LabeledStatement extends NodeBase {
14502
15095
  hasEffects(context) {
@@ -14518,17 +15111,22 @@ class LabeledStatement extends NodeBase {
14518
15111
  return bodyHasEffects;
14519
15112
  }
14520
15113
  include(context, includeChildrenRecursively) {
14521
- this.included = true;
15114
+ if (!this.included)
15115
+ this.includeNode(context);
14522
15116
  const { brokenFlow, includedLabels } = context;
14523
15117
  context.includedLabels = new Set();
14524
15118
  this.body.include(context, includeChildrenRecursively);
14525
15119
  if (includeChildrenRecursively || context.includedLabels.has(this.label.name)) {
14526
- this.label.include();
15120
+ this.label.include(context);
14527
15121
  context.includedLabels.delete(this.label.name);
14528
15122
  context.brokenFlow = brokenFlow;
14529
15123
  }
14530
15124
  context.includedLabels = new Set([...includedLabels, ...context.includedLabels]);
14531
15125
  }
15126
+ includeNode(context) {
15127
+ this.included = true;
15128
+ this.body.includePath(UNKNOWN_PATH, context);
15129
+ }
14532
15130
  render(code, options) {
14533
15131
  if (this.label.included) {
14534
15132
  this.label.render(code, options);
@@ -14539,6 +15137,7 @@ class LabeledStatement extends NodeBase {
14539
15137
  this.body.render(code, options);
14540
15138
  }
14541
15139
  }
15140
+ LabeledStatement.prototype.applyDeoptimizations = doNotDeoptimize;
14542
15141
 
14543
15142
  class LogicalExpression extends NodeBase {
14544
15143
  constructor() {
@@ -14563,6 +15162,10 @@ class LogicalExpression extends NodeBase {
14563
15162
  const unusedBranch = this.usedBranch === this.left ? this.right : this.left;
14564
15163
  this.usedBranch = null;
14565
15164
  unusedBranch.deoptimizePath(UNKNOWN_PATH);
15165
+ if (this.included) {
15166
+ // As we are not tracking inclusions, we just include everything
15167
+ unusedBranch.includePath(UNKNOWN_PATH, createInclusionContext());
15168
+ }
14566
15169
  const { scope: { context }, expressionsToBeDeoptimized } = this;
14567
15170
  this.expressionsToBeDeoptimized = parseAst_js.EMPTY_ARRAY;
14568
15171
  for (const expression of expressionsToBeDeoptimized) {
@@ -14585,23 +15188,25 @@ class LogicalExpression extends NodeBase {
14585
15188
  }
14586
15189
  getLiteralValueAtPath(path, recursionTracker, origin) {
14587
15190
  const usedBranch = this.getUsedBranch();
14588
- if (!usedBranch)
14589
- return UnknownValue;
14590
- this.expressionsToBeDeoptimized.push(origin);
14591
- return usedBranch.getLiteralValueAtPath(path, recursionTracker, origin);
15191
+ if (usedBranch) {
15192
+ this.expressionsToBeDeoptimized.push(origin);
15193
+ return usedBranch.getLiteralValueAtPath(path, recursionTracker, origin);
15194
+ }
15195
+ return UnknownValue;
14592
15196
  }
14593
15197
  getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin) {
14594
15198
  const usedBranch = this.getUsedBranch();
14595
- if (!usedBranch)
14596
- return [
14597
- new MultiExpression([
14598
- this.left.getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin)[0],
14599
- this.right.getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin)[0]
14600
- ]),
14601
- false
14602
- ];
14603
- this.expressionsToBeDeoptimized.push(origin);
14604
- return usedBranch.getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin);
15199
+ if (usedBranch) {
15200
+ this.expressionsToBeDeoptimized.push(origin);
15201
+ return usedBranch.getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin);
15202
+ }
15203
+ return [
15204
+ new MultiExpression([
15205
+ this.left.getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin)[0],
15206
+ this.right.getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin)[0]
15207
+ ]),
15208
+ false
15209
+ ];
14605
15210
  }
14606
15211
  hasEffects(context) {
14607
15212
  if (this.left.hasEffects(context)) {
@@ -14614,18 +15219,18 @@ class LogicalExpression extends NodeBase {
14614
15219
  }
14615
15220
  hasEffectsOnInteractionAtPath(path, interaction, context) {
14616
15221
  const usedBranch = this.getUsedBranch();
14617
- if (!usedBranch) {
14618
- return (this.left.hasEffectsOnInteractionAtPath(path, interaction, context) ||
14619
- this.right.hasEffectsOnInteractionAtPath(path, interaction, context));
15222
+ if (usedBranch) {
15223
+ return usedBranch.hasEffectsOnInteractionAtPath(path, interaction, context);
14620
15224
  }
14621
- return usedBranch.hasEffectsOnInteractionAtPath(path, interaction, context);
15225
+ return (this.left.hasEffectsOnInteractionAtPath(path, interaction, context) ||
15226
+ this.right.hasEffectsOnInteractionAtPath(path, interaction, context));
14622
15227
  }
14623
15228
  include(context, includeChildrenRecursively) {
14624
15229
  this.included = true;
14625
15230
  const usedBranch = this.getUsedBranch();
14626
15231
  if (includeChildrenRecursively ||
14627
- (usedBranch === this.right && this.left.shouldBeIncluded(context)) ||
14628
- !usedBranch) {
15232
+ !usedBranch ||
15233
+ (usedBranch === this.right && this.left.shouldBeIncluded(context))) {
14629
15234
  this.left.include(context, includeChildrenRecursively);
14630
15235
  this.right.include(context, includeChildrenRecursively);
14631
15236
  }
@@ -14633,6 +15238,17 @@ class LogicalExpression extends NodeBase {
14633
15238
  usedBranch.include(context, includeChildrenRecursively);
14634
15239
  }
14635
15240
  }
15241
+ includePath(path, context) {
15242
+ this.included = true;
15243
+ const usedBranch = this.getUsedBranch();
15244
+ if (!usedBranch || (usedBranch === this.right && this.left.shouldBeIncluded(context))) {
15245
+ this.left.includePath(path, context);
15246
+ this.right.includePath(path, context);
15247
+ }
15248
+ else {
15249
+ usedBranch.includePath(path, context);
15250
+ }
15251
+ }
14636
15252
  removeAnnotations(code) {
14637
15253
  this.left.removeAnnotations(code);
14638
15254
  }
@@ -14684,6 +15300,8 @@ class LogicalExpression extends NodeBase {
14684
15300
  return this.usedBranch;
14685
15301
  }
14686
15302
  }
15303
+ LogicalExpression.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
15304
+ LogicalExpression.prototype.applyDeoptimizations = doNotDeoptimize;
14687
15305
 
14688
15306
  class NewExpression extends NodeBase {
14689
15307
  hasEffects(context) {
@@ -14703,16 +15321,21 @@ class NewExpression extends NodeBase {
14703
15321
  return path.length > 0 || type !== INTERACTION_ACCESSED;
14704
15322
  }
14705
15323
  include(context, includeChildrenRecursively) {
14706
- if (!this.deoptimized)
14707
- this.applyDeoptimizations();
14708
15324
  if (includeChildrenRecursively) {
14709
15325
  super.include(context, includeChildrenRecursively);
14710
15326
  }
14711
15327
  else {
14712
- this.included = true;
15328
+ if (!this.included)
15329
+ this.includeNode(context);
14713
15330
  this.callee.include(context, false);
14714
15331
  }
14715
- this.callee.includeCallArguments(context, this.arguments);
15332
+ this.callee.includeCallArguments(context, this.interaction);
15333
+ }
15334
+ includeNode(context) {
15335
+ this.included = true;
15336
+ if (!this.deoptimized)
15337
+ this.applyDeoptimizations();
15338
+ this.callee.includePath(UNKNOWN_PATH, context);
14716
15339
  }
14717
15340
  initialise() {
14718
15341
  super.initialise();
@@ -14741,6 +15364,7 @@ class ObjectExpression extends NodeBase {
14741
15364
  constructor() {
14742
15365
  super(...arguments);
14743
15366
  this.objectEntity = null;
15367
+ this.protoProp = null;
14744
15368
  }
14745
15369
  deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
14746
15370
  this.getObjectEntity().deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker);
@@ -14760,15 +15384,43 @@ class ObjectExpression extends NodeBase {
14760
15384
  hasEffectsOnInteractionAtPath(path, interaction, context) {
14761
15385
  return this.getObjectEntity().hasEffectsOnInteractionAtPath(path, interaction, context);
14762
15386
  }
15387
+ include(context, includeChildrenRecursively) {
15388
+ if (!this.included)
15389
+ this.includeNode(context);
15390
+ this.getObjectEntity().include(context, includeChildrenRecursively);
15391
+ this.protoProp?.include(context, includeChildrenRecursively);
15392
+ }
15393
+ includeNode(context) {
15394
+ this.included = true;
15395
+ this.protoProp?.includePath(UNKNOWN_PATH, context);
15396
+ }
15397
+ includePath(path, context) {
15398
+ if (!this.included)
15399
+ this.includeNode(context);
15400
+ this.getObjectEntity().includePath(path, context);
15401
+ }
14763
15402
  render(code, options, { renderedSurroundingElement } = parseAst_js.BLANK) {
14764
- super.render(code, options);
14765
15403
  if (renderedSurroundingElement === parseAst_js.ExpressionStatement ||
14766
15404
  renderedSurroundingElement === parseAst_js.ArrowFunctionExpression) {
14767
15405
  code.appendRight(this.start, '(');
14768
15406
  code.prependLeft(this.end, ')');
14769
15407
  }
15408
+ if (this.properties.length > 0) {
15409
+ const separatedNodes = getCommaSeparatedNodesWithBoundaries(this.properties, code, this.start + 1, this.end - 1);
15410
+ let lastSeparatorPos = null;
15411
+ for (const { node, separator, start, end } of separatedNodes) {
15412
+ if (!node.included) {
15413
+ treeshakeNode(node, code, start, end);
15414
+ continue;
15415
+ }
15416
+ lastSeparatorPos = separator;
15417
+ node.render(code, options);
15418
+ }
15419
+ if (lastSeparatorPos) {
15420
+ code.remove(lastSeparatorPos, this.end - 1);
15421
+ }
15422
+ }
14770
15423
  }
14771
- applyDeoptimizations() { }
14772
15424
  getObjectEntity() {
14773
15425
  if (this.objectEntity !== null) {
14774
15426
  return this.objectEntity;
@@ -14797,6 +15449,7 @@ class ObjectExpression extends NodeBase {
14797
15449
  ? property.key.name
14798
15450
  : String(property.key.value);
14799
15451
  if (key === '__proto__' && property.kind === 'init') {
15452
+ this.protoProp = property;
14800
15453
  prototype =
14801
15454
  property.value instanceof Literal && property.value.value === null
14802
15455
  ? null
@@ -14809,6 +15462,7 @@ class ObjectExpression extends NodeBase {
14809
15462
  return (this.objectEntity = new ObjectEntity(properties, prototype));
14810
15463
  }
14811
15464
  }
15465
+ ObjectExpression.prototype.applyDeoptimizations = doNotDeoptimize;
14812
15466
 
14813
15467
  class PanicError extends NodeBase {
14814
15468
  initialise() {
@@ -14835,6 +15489,7 @@ class ParseError extends NodeBase {
14835
15489
 
14836
15490
  class PrivateIdentifier extends NodeBase {
14837
15491
  }
15492
+ PrivateIdentifier.prototype.includeNode = onlyIncludeSelf;
14838
15493
 
14839
15494
  class Program extends NodeBase {
14840
15495
  constructor() {
@@ -14902,14 +15557,11 @@ class Program extends NodeBase {
14902
15557
  super.render(code, options);
14903
15558
  }
14904
15559
  }
14905
- applyDeoptimizations() { }
14906
15560
  }
15561
+ Program.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
15562
+ Program.prototype.applyDeoptimizations = doNotDeoptimize;
14907
15563
 
14908
15564
  class Property extends MethodBase {
14909
- constructor() {
14910
- super(...arguments);
14911
- this.declarationInit = null;
14912
- }
14913
15565
  //declare method: boolean;
14914
15566
  get method() {
14915
15567
  return isFlagSet(this.flags, 262144 /* Flag.method */);
@@ -14924,17 +15576,41 @@ class Property extends MethodBase {
14924
15576
  set shorthand(value) {
14925
15577
  this.flags = setFlag(this.flags, 524288 /* Flag.shorthand */, value);
14926
15578
  }
14927
- declare(kind, init) {
14928
- this.declarationInit = init;
14929
- return this.value.declare(kind, UNKNOWN_EXPRESSION);
15579
+ declare(kind, destructuredInitPath, init) {
15580
+ return this.value.declare(kind, this.getPathInProperty(destructuredInitPath), init);
15581
+ }
15582
+ deoptimizeAssignment(destructuredInitPath, init) {
15583
+ this.value.deoptimizeAssignment?.(this.getPathInProperty(destructuredInitPath), init);
14930
15584
  }
14931
15585
  hasEffects(context) {
14932
- if (!this.deoptimized)
14933
- this.applyDeoptimizations();
14934
- const propertyReadSideEffects = this.scope.context.options.treeshake.propertyReadSideEffects;
14935
- return ((this.parent.type === 'ObjectPattern' && propertyReadSideEffects === 'always') ||
14936
- this.key.hasEffects(context) ||
14937
- this.value.hasEffects(context));
15586
+ return this.key.hasEffects(context) || this.value.hasEffects(context);
15587
+ }
15588
+ hasEffectsWhenDestructuring(context, destructuredInitPath, init) {
15589
+ return this.value.hasEffectsWhenDestructuring?.(context, this.getPathInProperty(destructuredInitPath), init);
15590
+ }
15591
+ includeDestructuredIfNecessary(context, destructuredInitPath, init) {
15592
+ const path = this.getPathInProperty(destructuredInitPath);
15593
+ let included = this.value.includeDestructuredIfNecessary(context, path, init) ||
15594
+ this.included;
15595
+ if ((included ||= this.key.hasEffects(createHasEffectsContext()))) {
15596
+ this.key.include(context, false);
15597
+ if (!this.value.included) {
15598
+ this.value.included = true;
15599
+ // Unfortunately, we need to include the value again now, so that any
15600
+ // declared variables are properly included.
15601
+ this.value.includeDestructuredIfNecessary(context, path, init);
15602
+ }
15603
+ }
15604
+ return (this.included = included);
15605
+ }
15606
+ include(context, includeChildrenRecursively) {
15607
+ this.included = true;
15608
+ this.key.include(context, includeChildrenRecursively);
15609
+ this.value.include(context, includeChildrenRecursively);
15610
+ }
15611
+ includePath(path, context) {
15612
+ this.included = true;
15613
+ this.value.includePath(path, context);
14938
15614
  }
14939
15615
  markDeclarationReached() {
14940
15616
  this.value.markDeclarationReached();
@@ -14945,14 +15621,20 @@ class Property extends MethodBase {
14945
15621
  }
14946
15622
  this.value.render(code, options, { isShorthandProperty: this.shorthand });
14947
15623
  }
14948
- applyDeoptimizations() {
14949
- this.deoptimized = true;
14950
- if (this.declarationInit !== null) {
14951
- this.declarationInit.deoptimizePath([UnknownKey, UnknownKey]);
14952
- this.scope.context.requestTreeshakingPass();
14953
- }
15624
+ getPathInProperty(destructuredInitPath) {
15625
+ return destructuredInitPath.at(-1) === UnknownKey
15626
+ ? destructuredInitPath
15627
+ : // For now, we only consider static paths as we do not know how to
15628
+ // deoptimize the path in the dynamic case.
15629
+ this.computed
15630
+ ? [...destructuredInitPath, UnknownKey]
15631
+ : this.key instanceof Identifier
15632
+ ? [...destructuredInitPath, this.key.name]
15633
+ : [...destructuredInitPath, String(this.key.value)];
14954
15634
  }
14955
15635
  }
15636
+ Property.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
15637
+ Property.prototype.applyDeoptimizations = doNotDeoptimize;
14956
15638
 
14957
15639
  class PropertyDefinition extends NodeBase {
14958
15640
  get computed() {
@@ -14985,8 +15667,15 @@ class PropertyDefinition extends NodeBase {
14985
15667
  hasEffectsOnInteractionAtPath(path, interaction, context) {
14986
15668
  return !this.value || this.value.hasEffectsOnInteractionAtPath(path, interaction, context);
14987
15669
  }
14988
- applyDeoptimizations() { }
15670
+ includeNode(context) {
15671
+ this.included = true;
15672
+ this.value?.includePath(UNKNOWN_PATH, context);
15673
+ for (const decorator of this.decorators) {
15674
+ decorator.includePath(UNKNOWN_PATH, context);
15675
+ }
15676
+ }
14989
15677
  }
15678
+ PropertyDefinition.prototype.applyDeoptimizations = doNotDeoptimize;
14990
15679
 
14991
15680
  class ReturnStatement extends NodeBase {
14992
15681
  hasEffects(context) {
@@ -14996,10 +15685,15 @@ class ReturnStatement extends NodeBase {
14996
15685
  return false;
14997
15686
  }
14998
15687
  include(context, includeChildrenRecursively) {
14999
- this.included = true;
15688
+ if (!this.included)
15689
+ this.includeNode(context);
15000
15690
  this.argument?.include(context, includeChildrenRecursively);
15001
15691
  context.brokenFlow = true;
15002
15692
  }
15693
+ includeNode(context) {
15694
+ this.included = true;
15695
+ this.argument?.includePath(UNKNOWN_PATH, context);
15696
+ }
15003
15697
  initialise() {
15004
15698
  super.initialise();
15005
15699
  this.scope.addReturnExpression(this.argument || UNKNOWN_EXPRESSION);
@@ -15013,6 +15707,7 @@ class ReturnStatement extends NodeBase {
15013
15707
  }
15014
15708
  }
15015
15709
  }
15710
+ ReturnStatement.prototype.applyDeoptimizations = doNotDeoptimize;
15016
15711
 
15017
15712
  class SequenceExpression extends NodeBase {
15018
15713
  deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
@@ -15040,10 +15735,15 @@ class SequenceExpression extends NodeBase {
15040
15735
  for (const expression of this.expressions) {
15041
15736
  if (includeChildrenRecursively ||
15042
15737
  (expression === lastExpression && !(this.parent instanceof ExpressionStatement)) ||
15043
- expression.shouldBeIncluded(context))
15738
+ expression.shouldBeIncluded(context)) {
15044
15739
  expression.include(context, includeChildrenRecursively);
15740
+ }
15045
15741
  }
15046
15742
  }
15743
+ includePath(path, context) {
15744
+ this.included = true;
15745
+ this.expressions[this.expressions.length - 1].includePath(path, context);
15746
+ }
15047
15747
  removeAnnotations(code) {
15048
15748
  this.expressions[0].removeAnnotations(code);
15049
15749
  }
@@ -15078,6 +15778,8 @@ class SequenceExpression extends NodeBase {
15078
15778
  }
15079
15779
  }
15080
15780
  }
15781
+ SequenceExpression.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
15782
+ SequenceExpression.prototype.applyDeoptimizations = doNotDeoptimize;
15081
15783
 
15082
15784
  class Super extends NodeBase {
15083
15785
  bind() {
@@ -15089,11 +15791,15 @@ class Super extends NodeBase {
15089
15791
  deoptimizePath(path) {
15090
15792
  this.variable.deoptimizePath(path);
15091
15793
  }
15092
- include() {
15093
- if (!this.included) {
15094
- this.included = true;
15095
- this.scope.context.includeVariableInModule(this.variable);
15096
- }
15794
+ include(context) {
15795
+ if (!this.included)
15796
+ this.includeNode(context);
15797
+ }
15798
+ includeNode(context) {
15799
+ this.included = true;
15800
+ if (!this.deoptimized)
15801
+ this.applyDeoptimizations();
15802
+ this.scope.context.includeVariableInModule(this.variable, EMPTY_PATH, context);
15097
15803
  }
15098
15804
  }
15099
15805
 
@@ -15134,6 +15840,8 @@ class SwitchCase extends NodeBase {
15134
15840
  }
15135
15841
  }
15136
15842
  SwitchCase.prototype.needsBoundaries = true;
15843
+ SwitchCase.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
15844
+ SwitchCase.prototype.applyDeoptimizations = doNotDeoptimize;
15137
15845
 
15138
15846
  class SwitchStatement extends NodeBase {
15139
15847
  createScope(parentScope) {
@@ -15216,6 +15924,8 @@ class SwitchStatement extends NodeBase {
15216
15924
  }
15217
15925
  }
15218
15926
  }
15927
+ SwitchStatement.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
15928
+ SwitchStatement.prototype.applyDeoptimizations = doNotDeoptimize;
15219
15929
 
15220
15930
  class TaggedTemplateExpression extends CallExpressionBase {
15221
15931
  bind() {
@@ -15239,8 +15949,8 @@ class TaggedTemplateExpression extends CallExpressionBase {
15239
15949
  this.tag.hasEffectsOnInteractionAtPath(EMPTY_PATH, this.interaction, context));
15240
15950
  }
15241
15951
  include(context, includeChildrenRecursively) {
15242
- if (!this.deoptimized)
15243
- this.applyDeoptimizations();
15952
+ if (!this.included)
15953
+ this.includeNode(context);
15244
15954
  if (includeChildrenRecursively) {
15245
15955
  super.include(context, includeChildrenRecursively);
15246
15956
  }
@@ -15249,7 +15959,7 @@ class TaggedTemplateExpression extends CallExpressionBase {
15249
15959
  this.tag.include(context, includeChildrenRecursively);
15250
15960
  this.quasi.include(context, includeChildrenRecursively);
15251
15961
  }
15252
- this.tag.includeCallArguments(context, this.args);
15962
+ this.tag.includeCallArguments(context, this.interaction);
15253
15963
  const [returnExpression] = this.getReturnExpression();
15254
15964
  if (!returnExpression.included) {
15255
15965
  returnExpression.include(context, false);
@@ -15284,6 +15994,7 @@ class TaggedTemplateExpression extends CallExpressionBase {
15284
15994
  return this.returnExpression;
15285
15995
  }
15286
15996
  }
15997
+ TaggedTemplateExpression.prototype.includeNode = onlyIncludeSelf;
15287
15998
 
15288
15999
  class TemplateElement extends NodeBase {
15289
16000
  get tail() {
@@ -15297,15 +16008,13 @@ class TemplateElement extends NodeBase {
15297
16008
  hasEffects() {
15298
16009
  return false;
15299
16010
  }
15300
- include() {
15301
- this.included = true;
15302
- }
15303
16011
  parseNode(esTreeNode) {
15304
16012
  this.value = esTreeNode.value;
15305
16013
  return super.parseNode(esTreeNode);
15306
16014
  }
15307
16015
  render() { }
15308
16016
  }
16017
+ TemplateElement.prototype.includeNode = onlyIncludeSelf;
15309
16018
 
15310
16019
  class TemplateLiteral extends NodeBase {
15311
16020
  deoptimizeArgumentsOnInteractionAtPath() { }
@@ -15330,6 +16039,14 @@ class TemplateLiteral extends NodeBase {
15330
16039
  }
15331
16040
  return true;
15332
16041
  }
16042
+ includeNode(context) {
16043
+ this.included = true;
16044
+ if (!this.deoptimized)
16045
+ this.applyDeoptimizations();
16046
+ for (const node of this.expressions) {
16047
+ node.includePath(UNKNOWN_PATH, context);
16048
+ }
16049
+ }
15333
16050
  render(code, options) {
15334
16051
  code.indentExclusionRanges.push([this.start, this.end]);
15335
16052
  super.render(code, options);
@@ -15339,13 +16056,13 @@ class TemplateLiteral extends NodeBase {
15339
16056
  class ModuleScope extends ChildScope {
15340
16057
  constructor(parent, context) {
15341
16058
  super(parent, context);
15342
- this.variables.set('this', new LocalVariable('this', null, UNDEFINED_EXPRESSION, context, 'other'));
16059
+ this.variables.set('this', new LocalVariable('this', null, UNDEFINED_EXPRESSION, EMPTY_PATH, context, 'other'));
15343
16060
  }
15344
- addDeclaration(identifier, context, init, kind) {
16061
+ addDeclaration(identifier, context, init, destructuredInitPath, kind) {
15345
16062
  if (this.context.module.importDescriptions.has(identifier.name)) {
15346
16063
  context.error(parseAst_js.logRedeclarationError(identifier.name), identifier.start);
15347
16064
  }
15348
- return super.addDeclaration(identifier, context, init, kind);
16065
+ return super.addDeclaration(identifier, context, init, destructuredInitPath, kind);
15349
16066
  }
15350
16067
  addExportDefaultDeclaration(name, exportDefaultDeclaration, context) {
15351
16068
  const variable = new ExportDefaultVariable(name, exportDefaultDeclaration, context);
@@ -15390,10 +16107,23 @@ class ThisExpression extends NodeBase {
15390
16107
  }
15391
16108
  return this.variable.hasEffectsOnInteractionAtPath(path, interaction, context);
15392
16109
  }
15393
- include() {
16110
+ include(context) {
16111
+ if (!this.included)
16112
+ this.includeNode(context);
16113
+ }
16114
+ includeNode(context) {
16115
+ this.included = true;
16116
+ if (!this.deoptimized)
16117
+ this.applyDeoptimizations();
16118
+ this.scope.context.includeVariableInModule(this.variable, EMPTY_PATH, context);
16119
+ }
16120
+ includePath(path, context) {
15394
16121
  if (!this.included) {
15395
16122
  this.included = true;
15396
- this.scope.context.includeVariableInModule(this.variable);
16123
+ this.scope.context.includeVariableInModule(this.variable, path, context);
16124
+ }
16125
+ else if (path.length > 0) {
16126
+ this.variable.includePath(path, context);
15397
16127
  }
15398
16128
  }
15399
16129
  initialise() {
@@ -15421,7 +16151,8 @@ class ThrowStatement extends NodeBase {
15421
16151
  return true;
15422
16152
  }
15423
16153
  include(context, includeChildrenRecursively) {
15424
- this.included = true;
16154
+ if (!this.included)
16155
+ this.includeNode(context);
15425
16156
  this.argument.include(context, includeChildrenRecursively);
15426
16157
  context.brokenFlow = true;
15427
16158
  }
@@ -15432,6 +16163,7 @@ class ThrowStatement extends NodeBase {
15432
16163
  }
15433
16164
  }
15434
16165
  }
16166
+ ThrowStatement.prototype.includeNode = onlyIncludeSelf;
15435
16167
 
15436
16168
  class TryStatement extends NodeBase {
15437
16169
  constructor() {
@@ -15468,6 +16200,8 @@ class TryStatement extends NodeBase {
15468
16200
  this.finalizer?.include(context, includeChildrenRecursively);
15469
16201
  }
15470
16202
  }
16203
+ TryStatement.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
16204
+ TryStatement.prototype.applyDeoptimizations = doNotDeoptimize;
15471
16205
 
15472
16206
  const unaryOperators = {
15473
16207
  '!': value => !value,
@@ -15513,6 +16247,7 @@ class UnaryExpression extends NodeBase {
15513
16247
  }
15514
16248
  }
15515
16249
  }
16250
+ UnaryExpression.prototype.includeNode = onlyIncludeSelf;
15516
16251
 
15517
16252
  class UpdateExpression extends NodeBase {
15518
16253
  hasEffects(context) {
@@ -15524,9 +16259,8 @@ class UpdateExpression extends NodeBase {
15524
16259
  return path.length > 1 || type !== INTERACTION_ACCESSED;
15525
16260
  }
15526
16261
  include(context, includeChildrenRecursively) {
15527
- if (!this.deoptimized)
15528
- this.applyDeoptimizations();
15529
- this.included = true;
16262
+ if (!this.included)
16263
+ this.includeNode(context);
15530
16264
  this.argument.includeAsAssignmentTarget(context, includeChildrenRecursively, true);
15531
16265
  }
15532
16266
  initialise() {
@@ -15565,6 +16299,7 @@ class UpdateExpression extends NodeBase {
15565
16299
  this.scope.context.requestTreeshakingPass();
15566
16300
  }
15567
16301
  }
16302
+ UpdateExpression.prototype.includeNode = onlyIncludeSelf;
15568
16303
 
15569
16304
  function areAllDeclarationsIncludedAndNotExported(declarations, exportNamesByVariable) {
15570
16305
  for (const declarator of declarations) {
@@ -15595,8 +16330,9 @@ class VariableDeclaration extends NodeBase {
15595
16330
  include(context, includeChildrenRecursively, { asSingleStatement } = parseAst_js.BLANK) {
15596
16331
  this.included = true;
15597
16332
  for (const declarator of this.declarations) {
15598
- if (includeChildrenRecursively || declarator.shouldBeIncluded(context))
16333
+ if (includeChildrenRecursively || declarator.shouldBeIncluded(context)) {
15599
16334
  declarator.include(context, includeChildrenRecursively);
16335
+ }
15600
16336
  const { id, init } = declarator;
15601
16337
  if (asSingleStatement) {
15602
16338
  id.include(context, includeChildrenRecursively);
@@ -15634,7 +16370,6 @@ class VariableDeclaration extends NodeBase {
15634
16370
  this.renderReplacedDeclarations(code, options);
15635
16371
  }
15636
16372
  }
15637
- applyDeoptimizations() { }
15638
16373
  renderDeclarationEnd(code, separatorString, lastSeparatorPos, actualContentEnd, renderedContentEnd, systemPatternExports, options) {
15639
16374
  if (code.original.charCodeAt(this.end - 1) === 59 /*";"*/) {
15640
16375
  code.remove(this.end - 1, this.end);
@@ -15677,8 +16412,7 @@ class VariableDeclaration extends NodeBase {
15677
16412
  const singleSystemExport = gatherSystemExportsAndGetSingleExport(separatedNodes, options, aggregatedSystemExports);
15678
16413
  for (const { node, start, separator, contentEnd, end } of separatedNodes) {
15679
16414
  if (!node.included) {
15680
- code.remove(start, end);
15681
- node.removeAnnotations(code);
16415
+ treeshakeNode(node, code, start, end);
15682
16416
  continue;
15683
16417
  }
15684
16418
  node.render(code, options);
@@ -15748,6 +16482,8 @@ function gatherSystemExportsAndGetSingleExport(separatedNodes, options, aggregat
15748
16482
  }
15749
16483
  return singleSystemExport;
15750
16484
  }
16485
+ VariableDeclaration.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
16486
+ VariableDeclaration.prototype.applyDeoptimizations = doNotDeoptimize;
15751
16487
 
15752
16488
  class WhileStatement extends NodeBase {
15753
16489
  hasEffects(context) {
@@ -15761,13 +16497,25 @@ class WhileStatement extends NodeBase {
15761
16497
  includeLoopBody(context, this.body, includeChildrenRecursively);
15762
16498
  }
15763
16499
  }
16500
+ WhileStatement.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
16501
+ WhileStatement.prototype.applyDeoptimizations = doNotDeoptimize;
15764
16502
 
15765
16503
  class YieldExpression extends NodeBase {
16504
+ applyDeoptimizations() {
16505
+ this.deoptimized = true;
16506
+ this.argument?.deoptimizePath(UNKNOWN_PATH);
16507
+ }
15766
16508
  hasEffects(context) {
15767
16509
  if (!this.deoptimized)
15768
16510
  this.applyDeoptimizations();
15769
16511
  return !(context.ignore.returnYield && !this.argument?.hasEffects(context));
15770
16512
  }
16513
+ includeNode(context) {
16514
+ this.included = true;
16515
+ if (!this.deoptimized)
16516
+ this.applyDeoptimizations();
16517
+ this.argument?.includePath(UNKNOWN_PATH, context);
16518
+ }
15771
16519
  render(code, options) {
15772
16520
  if (this.argument) {
15773
16521
  this.argument.render(code, options, { preventASI: true });
@@ -16001,7 +16749,7 @@ const bufferParsers = [
16001
16749
  const annotations = (node.annotations = parseAst_js.convertAnnotations(buffer[position + 1], buffer));
16002
16750
  node.annotationNoSideEffects = annotations.some(comment => comment.type === 'noSideEffects');
16003
16751
  const parameters = (node.params = convertNodeList(node, scope, buffer[position + 2], buffer));
16004
- scope.addParameterVariables(parameters.map(parameter => parameter.declare('parameter', UNKNOWN_EXPRESSION)), parameters[parameters.length - 1] instanceof RestElement);
16752
+ scope.addParameterVariables(parameters.map(parameter => parameter.declare('parameter', EMPTY_PATH, UNKNOWN_EXPRESSION)), parameters[parameters.length - 1] instanceof RestElement);
16005
16753
  node.body = convertNode(node, scope.bodyScope, buffer[position + 3], buffer);
16006
16754
  },
16007
16755
  function assignmentExpression(node, position, buffer) {
@@ -16047,7 +16795,7 @@ const bufferParsers = [
16047
16795
  const parameterPosition = buffer[position];
16048
16796
  const parameter = (node.param =
16049
16797
  parameterPosition === 0 ? null : convertNode(node, scope, parameterPosition, buffer));
16050
- parameter?.declare('parameter', UNKNOWN_EXPRESSION);
16798
+ parameter?.declare('parameter', EMPTY_PATH, UNKNOWN_EXPRESSION);
16051
16799
  node.body = convertNode(node, scope.bodyScope, buffer[position + 1], buffer);
16052
16800
  },
16053
16801
  function chainExpression(node, position, buffer) {
@@ -16185,7 +16933,7 @@ const bufferParsers = [
16185
16933
  node.id =
16186
16934
  idPosition === 0 ? null : convertNode(node, scope.parent, idPosition, buffer);
16187
16935
  const parameters = (node.params = convertNodeList(node, scope, buffer[position + 3], buffer));
16188
- scope.addParameterVariables(parameters.map(parameter => parameter.declare('parameter', UNKNOWN_EXPRESSION)), parameters[parameters.length - 1] instanceof RestElement);
16936
+ scope.addParameterVariables(parameters.map(parameter => parameter.declare('parameter', EMPTY_PATH, UNKNOWN_EXPRESSION)), parameters[parameters.length - 1] instanceof RestElement);
16189
16937
  node.body = convertNode(node, scope.bodyScope, buffer[position + 4], buffer);
16190
16938
  },
16191
16939
  function functionExpression(node, position, buffer) {
@@ -16198,7 +16946,7 @@ const bufferParsers = [
16198
16946
  const idPosition = buffer[position + 2];
16199
16947
  node.id = idPosition === 0 ? null : convertNode(node, node.idScope, idPosition, buffer);
16200
16948
  const parameters = (node.params = convertNodeList(node, scope, buffer[position + 3], buffer));
16201
- scope.addParameterVariables(parameters.map(parameter => parameter.declare('parameter', UNKNOWN_EXPRESSION)), parameters[parameters.length - 1] instanceof RestElement);
16949
+ scope.addParameterVariables(parameters.map(parameter => parameter.declare('parameter', EMPTY_PATH, UNKNOWN_EXPRESSION)), parameters[parameters.length - 1] instanceof RestElement);
16202
16950
  node.body = convertNode(node, scope.bodyScope, buffer[position + 4], buffer);
16203
16951
  },
16204
16952
  function identifier(node, position, buffer) {
@@ -16662,8 +17410,8 @@ class ExportShimVariable extends Variable {
16662
17410
  super(MISSING_EXPORT_SHIM_VARIABLE);
16663
17411
  this.module = module;
16664
17412
  }
16665
- include() {
16666
- super.include();
17413
+ includePath(path, context) {
17414
+ super.includePath(path, context);
16667
17415
  this.module.needsExportShim = true;
16668
17416
  }
16669
17417
  }
@@ -17354,16 +18102,15 @@ class Module {
17354
18102
  markModuleAndImpureDependenciesAsExecuted(this);
17355
18103
  this.graph.needsTreeshakingPass = true;
17356
18104
  }
18105
+ const inclusionContext = createInclusionContext();
17357
18106
  for (const exportName of this.exports.keys()) {
17358
18107
  if (includeNamespaceMembers || exportName !== this.info.syntheticNamedExports) {
17359
18108
  const variable = this.getVariableForExportName(exportName)[0];
17360
18109
  if (!variable) {
17361
18110
  return parseAst_js.error(parseAst_js.logMissingEntryExport(exportName, this.id));
17362
18111
  }
18112
+ this.includeVariable(variable, UNKNOWN_PATH, inclusionContext);
17363
18113
  variable.deoptimizePath(UNKNOWN_PATH);
17364
- if (!variable.included) {
17365
- this.includeVariable(variable);
17366
- }
17367
18114
  }
17368
18115
  }
17369
18116
  for (const name of this.getReexports()) {
@@ -17371,7 +18118,7 @@ class Module {
17371
18118
  if (variable) {
17372
18119
  variable.deoptimizePath(UNKNOWN_PATH);
17373
18120
  if (!variable.included) {
17374
- this.includeVariable(variable);
18121
+ this.includeVariable(variable, UNKNOWN_PATH, inclusionContext);
17375
18122
  }
17376
18123
  if (variable instanceof ExternalVariable) {
17377
18124
  variable.module.reexported = true;
@@ -17392,13 +18139,12 @@ class Module {
17392
18139
  this.graph.needsTreeshakingPass = true;
17393
18140
  }
17394
18141
  let includeNamespaceMembers = false;
18142
+ const inclusionContext = createInclusionContext();
17395
18143
  for (const name of names) {
17396
18144
  const variable = this.getVariableForExportName(name)[0];
17397
18145
  if (variable) {
17398
18146
  variable.deoptimizePath(UNKNOWN_PATH);
17399
- if (!variable.included) {
17400
- this.includeVariable(variable);
17401
- }
18147
+ this.includeVariable(variable, UNKNOWN_PATH, inclusionContext);
17402
18148
  }
17403
18149
  if (!this.exports.has(name) && !this.reexportDescriptions.has(name)) {
17404
18150
  includeNamespaceMembers = true;
@@ -17499,6 +18245,7 @@ class Module {
17499
18245
  manualPureFunctions: this.graph.pureFunctions,
17500
18246
  module: this,
17501
18247
  moduleContext: this.context,
18248
+ newlyIncludedVariableInits: this.graph.newlyIncludedVariableInits,
17502
18249
  options: this.options,
17503
18250
  requestTreeshakingPass: () => (this.graph.needsTreeshakingPass = true),
17504
18251
  traceExport: (name) => this.getVariableForExportName(name)[0],
@@ -17839,13 +18586,13 @@ class Module {
17839
18586
  for (const module of [this, ...this.exportAllModules]) {
17840
18587
  if (module instanceof ExternalModule) {
17841
18588
  const [externalVariable] = module.getVariableForExportName('*');
17842
- externalVariable.include();
18589
+ externalVariable.includePath(UNKNOWN_PATH, createInclusionContext());
17843
18590
  this.includedImports.add(externalVariable);
17844
18591
  externalNamespaces.add(externalVariable);
17845
18592
  }
17846
18593
  else if (module.info.syntheticNamedExports) {
17847
18594
  const syntheticNamespace = module.getSyntheticNamespace();
17848
- syntheticNamespace.include();
18595
+ syntheticNamespace.includePath(UNKNOWN_PATH, createInclusionContext());
17849
18596
  this.includedImports.add(syntheticNamespace);
17850
18597
  syntheticNamespaces.add(syntheticNamespace);
17851
18598
  }
@@ -17855,7 +18602,9 @@ class Module {
17855
18602
  includeDynamicImport(node) {
17856
18603
  const resolution = this.dynamicImports.find(dynamicImport => dynamicImport.node === node).resolution;
17857
18604
  if (resolution instanceof Module) {
17858
- resolution.includedDynamicImporters.push(this);
18605
+ if (!resolution.includedDynamicImporters.includes(this)) {
18606
+ resolution.includedDynamicImporters.push(this);
18607
+ }
17859
18608
  const importedNames = this.options.treeshake
17860
18609
  ? node.getDeterministicImportedNames()
17861
18610
  : undefined;
@@ -17867,15 +18616,15 @@ class Module {
17867
18616
  }
17868
18617
  }
17869
18618
  }
17870
- includeVariable(variable) {
17871
- const variableModule = variable.module;
17872
- if (variable.included) {
18619
+ includeVariable(variable, path, context) {
18620
+ const { included, module: variableModule } = variable;
18621
+ variable.includePath(path, context);
18622
+ if (included) {
17873
18623
  if (variableModule instanceof Module && variableModule !== this) {
17874
18624
  getAndExtendSideEffectModules(variable, this);
17875
18625
  }
17876
18626
  }
17877
18627
  else {
17878
- variable.include();
17879
18628
  this.graph.needsTreeshakingPass = true;
17880
18629
  if (variableModule instanceof Module) {
17881
18630
  if (!variableModule.isExecuted) {
@@ -17892,8 +18641,8 @@ class Module {
17892
18641
  }
17893
18642
  }
17894
18643
  }
17895
- includeVariableInModule(variable) {
17896
- this.includeVariable(variable);
18644
+ includeVariableInModule(variable, path, context) {
18645
+ this.includeVariable(variable, path, context);
17897
18646
  const variableModule = variable.module;
17898
18647
  if (variableModule && variableModule !== this) {
17899
18648
  this.includedImports.add(variable);
@@ -21396,10 +22145,11 @@ class Graph {
21396
22145
  this.options = options;
21397
22146
  this.astLru = flru(5);
21398
22147
  this.cachedModules = new Map();
21399
- this.deoptimizationTracker = new PathTracker();
22148
+ this.deoptimizationTracker = new EntityPathTracker();
21400
22149
  this.entryModules = [];
21401
22150
  this.modulesById = new Map();
21402
22151
  this.needsTreeshakingPass = false;
22152
+ this.newlyIncludedVariableInits = new Set();
21403
22153
  this.phase = BuildPhase.LOAD_AND_PARSE;
21404
22154
  this.scope = new GlobalScope();
21405
22155
  this.watchFiles = Object.create(null);
@@ -21493,6 +22243,7 @@ class Graph {
21493
22243
  }
21494
22244
  if (this.options.treeshake) {
21495
22245
  let treeshakingPass = 1;
22246
+ this.newlyIncludedVariableInits.clear();
21496
22247
  do {
21497
22248
  timeStart(`treeshaking pass ${treeshakingPass}`, 3);
21498
22249
  this.needsTreeshakingPass = false;
@@ -21517,6 +22268,10 @@ class Graph {
21517
22268
  }
21518
22269
  }
21519
22270
  }
22271
+ for (const entity of this.newlyIncludedVariableInits) {
22272
+ this.newlyIncludedVariableInits.delete(entity);
22273
+ entity.include(createInclusionContext(), false);
22274
+ }
21520
22275
  timeEnd(`treeshaking pass ${treeshakingPass++}`, 3);
21521
22276
  } while (this.needsTreeshakingPass);
21522
22277
  }