@rollup/wasm-node 4.28.0 → 4.29.0-0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  /*
2
2
  @license
3
- Rollup.js v4.28.0
4
- Sat, 30 Nov 2024 13:15:17 GMT - commit 0595e433edec3608bfc0331d8f02912374e7f7f7
3
+ Rollup.js v4.29.0-0
4
+ Mon, 16 Dec 2024 06:39:21 GMT - commit 879d03d68890f365f880e30c69b58377b8743407
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.0";
34
+ var version = "4.29.0-0";
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
@@ -6612,11 +6764,40 @@ function closestParentFunctionOrProgram(node) {
6612
6764
  return node;
6613
6765
  }
6614
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);
6787
+ }
6788
+ }
6789
+
6615
6790
  class Identifier extends IdentifierBase {
6616
6791
  constructor() {
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,25 @@ 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() {
8503
8750
  const { expressionsToBeDeoptimized, object } = this;
8504
8751
  this.expressionsToBeDeoptimized = parseAst_js.EMPTY_ARRAY;
8505
- this.propertyKey = UnknownKey;
8752
+ this.dynamicPropertyKey = this.propertyKey;
8506
8753
  object.deoptimizePath(UNKNOWN_PATH);
8754
+ if (this.included) {
8755
+ object.includePath(UNKNOWN_PATH, createInclusionContext());
8756
+ }
8507
8757
  for (const expression of expressionsToBeDeoptimized) {
8508
8758
  expression.deoptimizeCache();
8509
8759
  }
@@ -8514,11 +8764,13 @@ class MemberExpression extends NodeBase {
8514
8764
  if (this.variable) {
8515
8765
  this.variable.deoptimizePath(path);
8516
8766
  }
8517
- else if (!this.isUndefined && path.length < MAX_PATH_DEPTH) {
8518
- const propertyKey = this.getPropertyKey();
8767
+ else if (!this.isUndefined) {
8768
+ const { propertyKey } = this;
8519
8769
  this.object.deoptimizePath([
8520
8770
  propertyKey === UnknownKey ? UnknownNonAccessorKey : propertyKey,
8521
- ...path
8771
+ ...(path.length < MAX_PATH_DEPTH
8772
+ ? path
8773
+ : [...path.slice(0, MAX_PATH_DEPTH), UnknownKey])
8522
8774
  ]);
8523
8775
  }
8524
8776
  }
@@ -8529,9 +8781,10 @@ class MemberExpression extends NodeBase {
8529
8781
  if (this.isUndefined) {
8530
8782
  return undefined;
8531
8783
  }
8532
- if (this.propertyKey !== UnknownKey && path.length < MAX_PATH_DEPTH) {
8784
+ const propertyKey = this.getDynamicPropertyKey();
8785
+ if (propertyKey !== UnknownKey && path.length < MAX_PATH_DEPTH) {
8533
8786
  this.expressionsToBeDeoptimized.push(origin);
8534
- return this.object.getLiteralValueAtPath([this.getPropertyKey(), ...path], recursionTracker, origin);
8787
+ return this.object.getLiteralValueAtPath([propertyKey, ...path], recursionTracker, origin);
8535
8788
  }
8536
8789
  return UnknownValue;
8537
8790
  }
@@ -8551,9 +8804,10 @@ class MemberExpression extends NodeBase {
8551
8804
  if (this.isUndefined) {
8552
8805
  return [UNDEFINED_EXPRESSION, false];
8553
8806
  }
8554
- if (this.propertyKey !== UnknownKey && path.length < MAX_PATH_DEPTH) {
8807
+ const propertyKey = this.getDynamicPropertyKey();
8808
+ if (propertyKey !== UnknownKey && path.length < MAX_PATH_DEPTH) {
8555
8809
  this.expressionsToBeDeoptimized.push(origin);
8556
- return this.object.getReturnExpressionWhenCalledAtPath([this.getPropertyKey(), ...path], interaction, recursionTracker, origin);
8810
+ return this.object.getReturnExpressionWhenCalledAtPath([propertyKey, ...path], interaction, recursionTracker, origin);
8557
8811
  }
8558
8812
  return UNKNOWN_RETURN_EXPRESSION;
8559
8813
  }
@@ -8599,14 +8853,45 @@ class MemberExpression extends NodeBase {
8599
8853
  return true;
8600
8854
  }
8601
8855
  if (path.length < MAX_PATH_DEPTH) {
8602
- return this.object.hasEffectsOnInteractionAtPath([this.getPropertyKey(), ...path], interaction, context);
8856
+ return this.object.hasEffectsOnInteractionAtPath([this.getDynamicPropertyKey(), ...path], interaction, context);
8603
8857
  }
8604
8858
  return true;
8605
8859
  }
8860
+ hasEffectsWhenDestructuring(context, destructuredInitPath, init) {
8861
+ return (destructuredInitPath.length > 0 &&
8862
+ init.hasEffectsOnInteractionAtPath(destructuredInitPath, NODE_INTERACTION_UNKNOWN_ACCESS, context));
8863
+ }
8606
8864
  include(context, includeChildrenRecursively) {
8865
+ if (!this.included)
8866
+ this.includeNode(context);
8867
+ this.object.include(context, includeChildrenRecursively);
8868
+ this.property.include(context, includeChildrenRecursively);
8869
+ }
8870
+ includeNode(context) {
8871
+ this.included = true;
8607
8872
  if (!this.deoptimized)
8608
8873
  this.applyDeoptimizations();
8609
- this.includeProperties(context, includeChildrenRecursively);
8874
+ if (this.variable) {
8875
+ this.scope.context.includeVariableInModule(this.variable, EMPTY_PATH, context);
8876
+ }
8877
+ else if (!this.isUndefined) {
8878
+ this.object.includePath([this.propertyKey], context);
8879
+ }
8880
+ }
8881
+ includePath(path, context) {
8882
+ if (!this.included)
8883
+ this.includeNode(context);
8884
+ if (this.variable) {
8885
+ this.variable?.includePath(path, context);
8886
+ }
8887
+ else if (!this.isUndefined) {
8888
+ this.object.includePath([
8889
+ this.propertyKey,
8890
+ ...(path.length < MAX_PATH_DEPTH
8891
+ ? path
8892
+ : [...path.slice(0, MAX_PATH_DEPTH), UnknownKey])
8893
+ ], context);
8894
+ }
8610
8895
  }
8611
8896
  includeAsAssignmentTarget(context, includeChildrenRecursively, deoptimizeAccess) {
8612
8897
  if (!this.assignmentDeoptimized)
@@ -8615,20 +8900,34 @@ class MemberExpression extends NodeBase {
8615
8900
  this.include(context, includeChildrenRecursively);
8616
8901
  }
8617
8902
  else {
8618
- this.includeProperties(context, includeChildrenRecursively);
8903
+ if (!this.included)
8904
+ this.includeNode(context);
8905
+ this.object.include(context, includeChildrenRecursively);
8906
+ this.property.include(context, includeChildrenRecursively);
8619
8907
  }
8620
8908
  }
8621
- includeCallArguments(context, parameters) {
8909
+ includeCallArguments(context, interaction) {
8622
8910
  if (this.variable) {
8623
- this.variable.includeCallArguments(context, parameters);
8911
+ this.variable.includeCallArguments(context, interaction);
8624
8912
  }
8625
8913
  else {
8626
- super.includeCallArguments(context, parameters);
8914
+ super.includeCallArguments(context, interaction);
8915
+ }
8916
+ }
8917
+ includeDestructuredIfNecessary(context, destructuredInitPath, init) {
8918
+ if ((this.included ||=
8919
+ destructuredInitPath.length > 0 &&
8920
+ !context.brokenFlow &&
8921
+ init.hasEffectsOnInteractionAtPath(destructuredInitPath, NODE_INTERACTION_UNKNOWN_ACCESS, createHasEffectsContext()))) {
8922
+ init.include(context, false);
8923
+ return true;
8627
8924
  }
8925
+ return false;
8628
8926
  }
8629
8927
  initialise() {
8630
8928
  super.initialise();
8631
- this.propertyKey = getResolvablePropertyKey(this);
8929
+ this.dynamicPropertyKey = getResolvablePropertyKey(this);
8930
+ this.propertyKey = this.dynamicPropertyKey === null ? UnknownKey : this.dynamicPropertyKey;
8632
8931
  this.accessInteraction = { args: [this.object], type: INTERACTION_ACCESSED };
8633
8932
  }
8634
8933
  render(code, options, { renderedParentType, isCalleeOfRenderedParent, renderedSurroundingElement } = parseAst_js.BLANK) {
@@ -8665,8 +8964,7 @@ class MemberExpression extends NodeBase {
8665
8964
  this.bound &&
8666
8965
  propertyReadSideEffects &&
8667
8966
  !(this.variable || this.isUndefined)) {
8668
- const propertyKey = this.getPropertyKey();
8669
- this.object.deoptimizeArgumentsOnInteractionAtPath(this.accessInteraction, [propertyKey], SHARED_RECURSION_TRACKER);
8967
+ this.object.deoptimizeArgumentsOnInteractionAtPath(this.accessInteraction, [this.propertyKey], SHARED_RECURSION_TRACKER);
8670
8968
  this.scope.context.requestTreeshakingPass();
8671
8969
  }
8672
8970
  if (this.variable) {
@@ -8683,7 +8981,7 @@ class MemberExpression extends NodeBase {
8683
8981
  this.bound &&
8684
8982
  propertyReadSideEffects &&
8685
8983
  !(this.variable || this.isUndefined)) {
8686
- this.object.deoptimizeArgumentsOnInteractionAtPath(this.assignmentInteraction, [this.getPropertyKey()], SHARED_RECURSION_TRACKER);
8984
+ this.object.deoptimizeArgumentsOnInteractionAtPath(this.assignmentInteraction, [this.propertyKey], SHARED_RECURSION_TRACKER);
8687
8985
  this.scope.context.requestTreeshakingPass();
8688
8986
  }
8689
8987
  }
@@ -8692,24 +8990,24 @@ class MemberExpression extends NodeBase {
8692
8990
  const variable = this.scope.findVariable(this.object.name);
8693
8991
  if (variable.isNamespace) {
8694
8992
  if (this.variable) {
8695
- this.scope.context.includeVariableInModule(this.variable);
8993
+ this.scope.context.includeVariableInModule(this.variable, UNKNOWN_PATH, createInclusionContext());
8696
8994
  }
8697
8995
  this.scope.context.log(parseAst_js.LOGLEVEL_WARN, parseAst_js.logIllegalImportReassignment(this.object.name, this.scope.context.module.id), this.start);
8698
8996
  }
8699
8997
  }
8700
8998
  }
8701
- getPropertyKey() {
8702
- if (this.propertyKey === null) {
8703
- this.propertyKey = UnknownKey;
8999
+ getDynamicPropertyKey() {
9000
+ if (this.dynamicPropertyKey === null) {
9001
+ this.dynamicPropertyKey = UnknownKey;
8704
9002
  const value = this.property.getLiteralValueAtPath(EMPTY_PATH, SHARED_RECURSION_TRACKER, this);
8705
- return (this.propertyKey =
9003
+ return (this.dynamicPropertyKey =
8706
9004
  value === SymbolToStringTag
8707
9005
  ? value
8708
9006
  : typeof value === 'symbol'
8709
9007
  ? UnknownKey
8710
9008
  : String(value));
8711
9009
  }
8712
- return this.propertyKey;
9010
+ return this.dynamicPropertyKey;
8713
9011
  }
8714
9012
  hasAccessEffect(context) {
8715
9013
  const { propertyReadSideEffects } = this.scope.context.options
@@ -8717,17 +9015,7 @@ class MemberExpression extends NodeBase {
8717
9015
  return (!(this.variable || this.isUndefined) &&
8718
9016
  propertyReadSideEffects &&
8719
9017
  (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);
9018
+ this.object.hasEffectsOnInteractionAtPath([this.getDynamicPropertyKey()], this.accessInteraction, context)));
8731
9019
  }
8732
9020
  }
8733
9021
  function resolveNamespaceVariables(baseVariable, path, astContext) {
@@ -8771,18 +9059,20 @@ class MetaProperty extends NodeBase {
8771
9059
  return path.length > 1 || type !== INTERACTION_ACCESSED;
8772
9060
  }
8773
9061
  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
- }
9062
+ if (!this.included)
9063
+ this.includeNode();
9064
+ }
9065
+ includeNode() {
9066
+ this.included = true;
9067
+ if (this.meta.name === IMPORT) {
9068
+ this.scope.context.addImportMeta(this);
9069
+ const parent = this.parent;
9070
+ const metaProperty = (this.metaProperty =
9071
+ parent instanceof MemberExpression && typeof parent.propertyKey === 'string'
9072
+ ? parent.propertyKey
9073
+ : null);
9074
+ if (metaProperty?.startsWith(FILE_PREFIX)) {
9075
+ this.referenceId = metaProperty.slice(FILE_PREFIX.length);
8786
9076
  }
8787
9077
  }
8788
9078
  }
@@ -8889,7 +9179,7 @@ class UndefinedVariable extends Variable {
8889
9179
 
8890
9180
  class ExportDefaultVariable extends LocalVariable {
8891
9181
  constructor(name, exportDefaultDeclaration, context) {
8892
- super(name, exportDefaultDeclaration, exportDefaultDeclaration.declaration, context, 'other');
9182
+ super(name, exportDefaultDeclaration, exportDefaultDeclaration.declaration, EMPTY_PATH, context, 'other');
8893
9183
  this.hasId = false;
8894
9184
  this.originalId = null;
8895
9185
  this.originalVariable = null;
@@ -9038,8 +9328,8 @@ class NamespaceVariable extends Variable {
9038
9328
  return (!memberVariable ||
9039
9329
  memberVariable.hasEffectsOnInteractionAtPath(path.slice(1), interaction, context));
9040
9330
  }
9041
- include() {
9042
- super.include();
9331
+ includePath(path, context) {
9332
+ super.includePath(path, context);
9043
9333
  this.context.includeAllExports();
9044
9334
  }
9045
9335
  prepare(accessedGlobalsByScope) {
@@ -9132,9 +9422,9 @@ class SyntheticNamedExportVariable extends Variable {
9132
9422
  getName(getPropertyAccess) {
9133
9423
  return `${this.syntheticNamespace.getName(getPropertyAccess)}${getPropertyAccess(this.name)}`;
9134
9424
  }
9135
- include() {
9136
- super.include();
9137
- this.context.includeVariableInModule(this.syntheticNamespace);
9425
+ includePath(path, context) {
9426
+ super.includePath(path, context);
9427
+ this.context.includeVariableInModule(this.syntheticNamespace, path, context);
9138
9428
  }
9139
9429
  setRenderNames(baseName, name) {
9140
9430
  super.setRenderNames(baseName, name);
@@ -12333,21 +12623,37 @@ class ArrayPattern extends NodeBase {
12333
12623
  element?.addExportedVariables(variables, exportNamesByVariable);
12334
12624
  }
12335
12625
  }
12336
- declare(kind) {
12626
+ declare(kind, destructuredInitPath, init) {
12337
12627
  const variables = [];
12628
+ const includedPatternPath = getIncludedPatternPath(destructuredInitPath);
12338
12629
  for (const element of this.elements) {
12339
12630
  if (element !== null) {
12340
- variables.push(...element.declare(kind, UNKNOWN_EXPRESSION));
12631
+ variables.push(...element.declare(kind, includedPatternPath, init));
12341
12632
  }
12342
12633
  }
12343
12634
  return variables;
12344
12635
  }
12636
+ deoptimizeAssignment(destructuredInitPath, init) {
12637
+ const includedPatternPath = getIncludedPatternPath(destructuredInitPath);
12638
+ for (const element of this.elements) {
12639
+ element?.deoptimizeAssignment(includedPatternPath, init);
12640
+ }
12641
+ }
12345
12642
  // Patterns can only be deoptimized at the empty path at the moment
12346
12643
  deoptimizePath() {
12347
12644
  for (const element of this.elements) {
12348
12645
  element?.deoptimizePath(EMPTY_PATH);
12349
12646
  }
12350
12647
  }
12648
+ hasEffectsWhenDestructuring(context, destructuredInitPath, init) {
12649
+ const includedPatternPath = getIncludedPatternPath(destructuredInitPath);
12650
+ for (const element of this.elements) {
12651
+ if (element?.hasEffectsWhenDestructuring(context, includedPatternPath, init)) {
12652
+ return true;
12653
+ }
12654
+ }
12655
+ return false;
12656
+ }
12351
12657
  // Patterns are only checked at the empty path at the moment
12352
12658
  hasEffectsOnInteractionAtPath(_path, interaction, context) {
12353
12659
  for (const element of this.elements) {
@@ -12356,12 +12662,38 @@ class ArrayPattern extends NodeBase {
12356
12662
  }
12357
12663
  return false;
12358
12664
  }
12665
+ includeDestructuredIfNecessary(context, destructuredInitPath, init) {
12666
+ let included = false;
12667
+ const includedPatternPath = getIncludedPatternPath(destructuredInitPath);
12668
+ for (const element of this.elements) {
12669
+ if (element) {
12670
+ element.included ||= included;
12671
+ included =
12672
+ element.includeDestructuredIfNecessary(context, includedPatternPath, init) || included;
12673
+ }
12674
+ }
12675
+ if (included) {
12676
+ // This is necessary so that if any pattern element is included, all are
12677
+ // included for proper deconflicting
12678
+ for (const element of this.elements) {
12679
+ if (element && !element.included) {
12680
+ element.included = true;
12681
+ element.includeDestructuredIfNecessary(context, includedPatternPath, init);
12682
+ }
12683
+ }
12684
+ }
12685
+ return (this.included ||= included);
12686
+ }
12359
12687
  markDeclarationReached() {
12360
12688
  for (const element of this.elements) {
12361
12689
  element?.markDeclarationReached();
12362
12690
  }
12363
12691
  }
12364
12692
  }
12693
+ ArrayPattern.prototype.includeNode = onlyIncludeSelf;
12694
+ const getIncludedPatternPath = (destructuredInitPath) => destructuredInitPath.at(-1) === UnknownKey
12695
+ ? destructuredInitPath
12696
+ : [...destructuredInitPath, UnknownInteger];
12365
12697
 
12366
12698
  class ArrowFunctionExpression extends FunctionBase {
12367
12699
  constructor() {
@@ -12378,8 +12710,6 @@ class ArrowFunctionExpression extends FunctionBase {
12378
12710
  this.scope = new ReturnValueScope(parentScope, false);
12379
12711
  }
12380
12712
  hasEffects() {
12381
- if (!this.deoptimized)
12382
- this.applyDeoptimizations();
12383
12713
  return false;
12384
12714
  }
12385
12715
  hasEffectsOnInteractionAtPath(path, interaction, context) {
@@ -12418,6 +12748,15 @@ class ArrowFunctionExpression extends FunctionBase {
12418
12748
  }
12419
12749
  }
12420
12750
  }
12751
+ includeNode(context) {
12752
+ this.included = true;
12753
+ this.body.includePath(UNKNOWN_PATH, context);
12754
+ for (const parameter of this.params) {
12755
+ if (!(parameter instanceof Identifier)) {
12756
+ parameter.includePath(UNKNOWN_PATH, context);
12757
+ }
12758
+ }
12759
+ }
12421
12760
  getObjectEntity() {
12422
12761
  if (this.objectEntity !== null) {
12423
12762
  return this.objectEntity;
@@ -12437,13 +12776,18 @@ class ObjectPattern extends NodeBase {
12437
12776
  }
12438
12777
  }
12439
12778
  }
12440
- declare(kind, init) {
12779
+ declare(kind, destructuredInitPath, init) {
12441
12780
  const variables = [];
12442
12781
  for (const property of this.properties) {
12443
- variables.push(...property.declare(kind, init));
12782
+ variables.push(...property.declare(kind, destructuredInitPath, init));
12444
12783
  }
12445
12784
  return variables;
12446
12785
  }
12786
+ deoptimizeAssignment(destructuredInitPath, init) {
12787
+ for (const property of this.properties) {
12788
+ property.deoptimizeAssignment(destructuredInitPath, init);
12789
+ }
12790
+ }
12447
12791
  deoptimizePath(path) {
12448
12792
  if (path.length === 0) {
12449
12793
  for (const property of this.properties) {
@@ -12461,12 +12805,46 @@ class ObjectPattern extends NodeBase {
12461
12805
  }
12462
12806
  return false;
12463
12807
  }
12808
+ hasEffectsWhenDestructuring(context, destructuredInitPath, init) {
12809
+ for (const property of this.properties) {
12810
+ if (property.hasEffectsWhenDestructuring(context, destructuredInitPath, init))
12811
+ return true;
12812
+ }
12813
+ return false;
12814
+ }
12815
+ includeDestructuredIfNecessary(context, destructuredInitPath, init) {
12816
+ let included = false;
12817
+ for (const property of this.properties) {
12818
+ included =
12819
+ property.includeDestructuredIfNecessary(context, destructuredInitPath, init) || included;
12820
+ }
12821
+ return (this.included ||= included);
12822
+ }
12464
12823
  markDeclarationReached() {
12465
12824
  for (const property of this.properties) {
12466
12825
  property.markDeclarationReached();
12467
12826
  }
12468
12827
  }
12828
+ render(code, options) {
12829
+ if (this.properties.length > 0) {
12830
+ const separatedNodes = getCommaSeparatedNodesWithBoundaries(this.properties, code, this.start + 1, this.end - 1);
12831
+ let lastSeparatorPos = null;
12832
+ for (const { node, separator, start, end } of separatedNodes) {
12833
+ if (!node.included) {
12834
+ treeshakeNode(node, code, start, end);
12835
+ continue;
12836
+ }
12837
+ lastSeparatorPos = separator;
12838
+ node.render(code, options);
12839
+ }
12840
+ if (lastSeparatorPos) {
12841
+ code.remove(lastSeparatorPos, this.end - 1);
12842
+ }
12843
+ }
12844
+ }
12469
12845
  }
12846
+ ObjectPattern.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
12847
+ ObjectPattern.prototype.applyDeoptimizations = doNotDeoptimize;
12470
12848
 
12471
12849
  class AssignmentExpression extends NodeBase {
12472
12850
  hasEffects(context) {
@@ -12475,7 +12853,9 @@ class AssignmentExpression extends NodeBase {
12475
12853
  this.applyDeoptimizations();
12476
12854
  // MemberExpressions do not access the property before assignments if the
12477
12855
  // operator is '='.
12478
- return (right.hasEffects(context) || left.hasEffectsAsAssignmentTarget(context, operator !== '='));
12856
+ return (right.hasEffects(context) ||
12857
+ left.hasEffectsAsAssignmentTarget(context, operator !== '=') ||
12858
+ this.left.hasEffectsWhenDestructuring?.(context, EMPTY_PATH, right));
12479
12859
  }
12480
12860
  hasEffectsOnInteractionAtPath(path, interaction, context) {
12481
12861
  return this.right.hasEffectsOnInteractionAtPath(path, interaction, context);
@@ -12484,15 +12864,24 @@ class AssignmentExpression extends NodeBase {
12484
12864
  const { deoptimized, left, right, operator } = this;
12485
12865
  if (!deoptimized)
12486
12866
  this.applyDeoptimizations();
12487
- this.included = true;
12867
+ if (!this.included)
12868
+ this.includeNode(context);
12869
+ const hasEffectsContext = createHasEffectsContext();
12488
12870
  if (includeChildrenRecursively ||
12489
12871
  operator !== '=' ||
12490
12872
  left.included ||
12491
- left.hasEffectsAsAssignmentTarget(createHasEffectsContext(), false)) {
12873
+ left.hasEffectsAsAssignmentTarget(hasEffectsContext, false) ||
12874
+ left.hasEffectsWhenDestructuring?.(hasEffectsContext, EMPTY_PATH, right)) {
12492
12875
  left.includeAsAssignmentTarget(context, includeChildrenRecursively, operator !== '=');
12493
12876
  }
12494
12877
  right.include(context, includeChildrenRecursively);
12495
12878
  }
12879
+ includeNode(context) {
12880
+ this.included = true;
12881
+ if (!this.deoptimized)
12882
+ this.applyDeoptimizations();
12883
+ this.right.includePath(UNKNOWN_PATH, context);
12884
+ }
12496
12885
  initialise() {
12497
12886
  super.initialise();
12498
12887
  if (this.left instanceof Identifier) {
@@ -12553,8 +12942,7 @@ class AssignmentExpression extends NodeBase {
12553
12942
  }
12554
12943
  applyDeoptimizations() {
12555
12944
  this.deoptimized = true;
12556
- this.left.deoptimizePath(EMPTY_PATH);
12557
- this.right.deoptimizePath(UNKNOWN_PATH);
12945
+ this.left.deoptimizeAssignment(EMPTY_PATH, this.right);
12558
12946
  this.scope.context.requestTreeshakingPass();
12559
12947
  }
12560
12948
  }
@@ -12563,8 +12951,11 @@ class AssignmentPattern extends NodeBase {
12563
12951
  addExportedVariables(variables, exportNamesByVariable) {
12564
12952
  this.left.addExportedVariables(variables, exportNamesByVariable);
12565
12953
  }
12566
- declare(kind, init) {
12567
- return this.left.declare(kind, init);
12954
+ declare(kind, destructuredInitPath, init) {
12955
+ return this.left.declare(kind, destructuredInitPath, init);
12956
+ }
12957
+ deoptimizeAssignment(destructuredInitPath, init) {
12958
+ this.left.deoptimizeAssignment(destructuredInitPath, init);
12568
12959
  }
12569
12960
  deoptimizePath(path) {
12570
12961
  if (path.length === 0) {
@@ -12574,6 +12965,29 @@ class AssignmentPattern extends NodeBase {
12574
12965
  hasEffectsOnInteractionAtPath(path, interaction, context) {
12575
12966
  return (path.length > 0 || this.left.hasEffectsOnInteractionAtPath(EMPTY_PATH, interaction, context));
12576
12967
  }
12968
+ hasEffectsWhenDestructuring(context, destructuredInitPath, init) {
12969
+ return this.left.hasEffectsWhenDestructuring(context, destructuredInitPath, init);
12970
+ }
12971
+ includeDestructuredIfNecessary(context, destructuredInitPath, init) {
12972
+ let included = this.left.includeDestructuredIfNecessary(context, destructuredInitPath, init) ||
12973
+ this.included;
12974
+ if ((included ||= this.right.shouldBeIncluded(context))) {
12975
+ this.right.include(context, false);
12976
+ if (!this.left.included) {
12977
+ this.left.included = true;
12978
+ // Unfortunately, we need to include the left side again now, so that
12979
+ // any declared variables are properly included.
12980
+ this.left.includeDestructuredIfNecessary(context, destructuredInitPath, init);
12981
+ }
12982
+ }
12983
+ return (this.included = included);
12984
+ }
12985
+ includeNode(context) {
12986
+ this.included = true;
12987
+ if (!this.deoptimized)
12988
+ this.applyDeoptimizations();
12989
+ this.right.includePath(UNKNOWN_PATH, context);
12990
+ }
12577
12991
  markDeclarationReached() {
12578
12992
  this.left.markDeclarationReached();
12579
12993
  }
@@ -12596,22 +13010,34 @@ class AwaitExpression extends NodeBase {
12596
13010
  return true;
12597
13011
  }
12598
13012
  include(context, includeChildrenRecursively) {
13013
+ if (!this.included)
13014
+ this.includeNode(context);
13015
+ this.argument.include(context, includeChildrenRecursively);
13016
+ }
13017
+ includeNode(context) {
13018
+ this.included = true;
12599
13019
  if (!this.deoptimized)
12600
13020
  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
- }
13021
+ checkTopLevelAwait: if (!this.scope.context.usesTopLevelAwait) {
13022
+ let parent = this.parent;
13023
+ do {
13024
+ if (parent instanceof FunctionNode || parent instanceof ArrowFunctionExpression)
13025
+ break checkTopLevelAwait;
13026
+ } while ((parent = parent.parent));
13027
+ this.scope.context.usesTopLevelAwait = true;
12611
13028
  }
12612
- this.argument.include(context, includeChildrenRecursively);
13029
+ // Thenables need to be included
13030
+ this.argument.includePath(THEN_PATH, context);
13031
+ }
13032
+ includePath(path, context) {
13033
+ if (!this.deoptimized)
13034
+ this.applyDeoptimizations();
13035
+ if (!this.included)
13036
+ this.includeNode(context);
13037
+ this.argument.includePath(path, context);
12613
13038
  }
12614
13039
  }
13040
+ const THEN_PATH = ['then'];
12615
13041
 
12616
13042
  const binaryOperators = {
12617
13043
  '!=': (left, right) => left != right,
@@ -12675,6 +13101,8 @@ class BinaryExpression extends NodeBase {
12675
13101
  this.right.render(code, options);
12676
13102
  }
12677
13103
  }
13104
+ BinaryExpression.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
13105
+ BinaryExpression.prototype.applyDeoptimizations = doNotDeoptimize;
12678
13106
 
12679
13107
  class BreakStatement extends NodeBase {
12680
13108
  hasEffects(context) {
@@ -12694,7 +13122,7 @@ class BreakStatement extends NodeBase {
12694
13122
  include(context) {
12695
13123
  this.included = true;
12696
13124
  if (this.label) {
12697
- this.label.include();
13125
+ this.label.include(context);
12698
13126
  context.includedLabels.add(this.label.name);
12699
13127
  }
12700
13128
  else {
@@ -12703,6 +13131,8 @@ class BreakStatement extends NodeBase {
12703
13131
  context.brokenFlow = true;
12704
13132
  }
12705
13133
  }
13134
+ BreakStatement.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
13135
+ BreakStatement.prototype.applyDeoptimizations = doNotDeoptimize;
12706
13136
 
12707
13137
  function renderCallArguments(code, options, node) {
12708
13138
  if (node.arguments.length > 0) {
@@ -12889,8 +13319,6 @@ class CallExpression extends CallExpressionBase {
12889
13319
  this.callee.hasEffectsOnInteractionAtPath(EMPTY_PATH, this.interaction, context)));
12890
13320
  }
12891
13321
  include(context, includeChildrenRecursively) {
12892
- if (!this.deoptimized)
12893
- this.applyDeoptimizations();
12894
13322
  if (includeChildrenRecursively) {
12895
13323
  super.include(context, includeChildrenRecursively);
12896
13324
  if (includeChildrenRecursively === INCLUDE_PARAMETERS &&
@@ -12900,10 +13328,26 @@ class CallExpression extends CallExpressionBase {
12900
13328
  }
12901
13329
  }
12902
13330
  else {
12903
- this.included = true;
12904
- this.callee.include(context, false);
13331
+ if (!this.included)
13332
+ this.includeNode(context);
13333
+ // If the callee is a member expression and does not have a variable, its
13334
+ // object will already be included via the first argument of the
13335
+ // interaction in includeCallArguments. Including it again can lead to
13336
+ // severe performance problems.
13337
+ if (this.callee instanceof MemberExpression && !this.callee.variable) {
13338
+ this.callee.property.include(context, false);
13339
+ }
13340
+ else {
13341
+ this.callee.include(context, false);
13342
+ }
13343
+ this.callee.includeCallArguments(context, this.interaction);
12905
13344
  }
12906
- this.callee.includeCallArguments(context, this.arguments);
13345
+ }
13346
+ includeNode(context) {
13347
+ this.included = true;
13348
+ if (!this.deoptimized)
13349
+ this.applyDeoptimizations();
13350
+ this.callee.includePath(UNKNOWN_PATH, context);
12907
13351
  }
12908
13352
  initialise() {
12909
13353
  super.initialise();
@@ -12942,13 +13386,14 @@ class CatchClause extends NodeBase {
12942
13386
  this.type = type;
12943
13387
  if (param) {
12944
13388
  this.param = new (this.scope.context.getNodeConstructor(param.type))(this, this.scope).parseNode(param);
12945
- this.param.declare('parameter', UNKNOWN_EXPRESSION);
13389
+ this.param.declare('parameter', EMPTY_PATH, UNKNOWN_EXPRESSION);
12946
13390
  }
12947
13391
  this.body = new BlockStatement(this, this.scope.bodyScope).parseNode(body);
12948
13392
  return super.parseNode(esTreeNode);
12949
13393
  }
12950
13394
  }
12951
13395
  CatchClause.prototype.preventChildBlockScope = true;
13396
+ CatchClause.prototype.includeNode = onlyIncludeSelf;
12952
13397
 
12953
13398
  class ChainExpression extends NodeBase {
12954
13399
  // deoptimizations are not relevant as we are not caching values
@@ -12960,17 +13405,22 @@ class ChainExpression extends NodeBase {
12960
13405
  hasEffects(context) {
12961
13406
  return this.expression.hasEffectsAsChainElement(context) === true;
12962
13407
  }
13408
+ includePath(path, context) {
13409
+ this.included = true;
13410
+ this.expression.includePath(path, context);
13411
+ }
12963
13412
  removeAnnotations(code) {
12964
13413
  this.expression.removeAnnotations(code);
12965
13414
  }
12966
- applyDeoptimizations() { }
12967
13415
  }
13416
+ ChainExpression.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
13417
+ ChainExpression.prototype.applyDeoptimizations = doNotDeoptimize;
12968
13418
 
12969
13419
  class ClassBodyScope extends ChildScope {
12970
13420
  constructor(parent, classNode) {
12971
13421
  const { context } = parent;
12972
13422
  super(parent, context);
12973
- this.variables.set('this', (this.thisVariable = new LocalVariable('this', null, classNode, context, 'other')));
13423
+ this.variables.set('this', (this.thisVariable = new LocalVariable('this', null, classNode, EMPTY_PATH, context, 'other')));
12974
13424
  this.instanceScope = new ChildScope(this, context);
12975
13425
  this.instanceScope.variables.set('this', new ThisVariable(context));
12976
13426
  }
@@ -12985,7 +13435,7 @@ class ClassBody extends NodeBase {
12985
13435
  }
12986
13436
  include(context, includeChildrenRecursively) {
12987
13437
  this.included = true;
12988
- this.scope.context.includeVariableInModule(this.scope.thisVariable);
13438
+ this.scope.context.includeVariableInModule(this.scope.thisVariable, UNKNOWN_PATH, context);
12989
13439
  for (const definition of this.body) {
12990
13440
  definition.include(context, includeChildrenRecursively);
12991
13441
  }
@@ -12998,8 +13448,9 @@ class ClassBody extends NodeBase {
12998
13448
  }
12999
13449
  return super.parseNode(esTreeNode);
13000
13450
  }
13001
- applyDeoptimizations() { }
13002
13451
  }
13452
+ ClassBody.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
13453
+ ClassBody.prototype.applyDeoptimizations = doNotDeoptimize;
13003
13454
 
13004
13455
  class ClassExpression extends ClassNode {
13005
13456
  render(code, options, { renderedSurroundingElement } = parseAst_js.BLANK) {
@@ -13057,6 +13508,9 @@ class ConditionalExpression extends NodeBase {
13057
13508
  const unusedBranch = this.usedBranch === this.consequent ? this.alternate : this.consequent;
13058
13509
  this.usedBranch = null;
13059
13510
  unusedBranch.deoptimizePath(UNKNOWN_PATH);
13511
+ if (this.included) {
13512
+ unusedBranch.includePath(UNKNOWN_PATH, createInclusionContext());
13513
+ }
13060
13514
  const { expressionsToBeDeoptimized } = this;
13061
13515
  this.expressionsToBeDeoptimized = parseAst_js.EMPTY_ARRAY;
13062
13516
  for (const expression of expressionsToBeDeoptimized) {
@@ -13114,7 +13568,7 @@ class ConditionalExpression extends NodeBase {
13114
13568
  include(context, includeChildrenRecursively) {
13115
13569
  this.included = true;
13116
13570
  const usedBranch = this.getUsedBranch();
13117
- if (includeChildrenRecursively || this.test.shouldBeIncluded(context) || usedBranch === null) {
13571
+ if (usedBranch === null || includeChildrenRecursively || this.test.shouldBeIncluded(context)) {
13118
13572
  this.test.include(context, includeChildrenRecursively);
13119
13573
  this.consequent.include(context, includeChildrenRecursively);
13120
13574
  this.alternate.include(context, includeChildrenRecursively);
@@ -13123,27 +13577,38 @@ class ConditionalExpression extends NodeBase {
13123
13577
  usedBranch.include(context, includeChildrenRecursively);
13124
13578
  }
13125
13579
  }
13126
- includeCallArguments(context, parameters) {
13580
+ includePath(path, context) {
13581
+ this.included = true;
13582
+ const usedBranch = this.getUsedBranch();
13583
+ if (usedBranch === null || this.test.shouldBeIncluded(context)) {
13584
+ this.consequent.includePath(path, context);
13585
+ this.alternate.includePath(path, context);
13586
+ }
13587
+ else {
13588
+ usedBranch.includePath(path, context);
13589
+ }
13590
+ }
13591
+ includeCallArguments(context, interaction) {
13127
13592
  const usedBranch = this.getUsedBranch();
13128
13593
  if (usedBranch) {
13129
- usedBranch.includeCallArguments(context, parameters);
13594
+ usedBranch.includeCallArguments(context, interaction);
13130
13595
  }
13131
13596
  else {
13132
- this.consequent.includeCallArguments(context, parameters);
13133
- this.alternate.includeCallArguments(context, parameters);
13597
+ this.consequent.includeCallArguments(context, interaction);
13598
+ this.alternate.includeCallArguments(context, interaction);
13134
13599
  }
13135
13600
  }
13136
13601
  removeAnnotations(code) {
13137
13602
  this.test.removeAnnotations(code);
13138
13603
  }
13139
13604
  render(code, options, { isCalleeOfRenderedParent, preventASI, renderedParentType, renderedSurroundingElement } = parseAst_js.BLANK) {
13140
- const usedBranch = this.getUsedBranch();
13141
13605
  if (this.test.included) {
13142
13606
  this.test.render(code, options, { renderedSurroundingElement });
13143
13607
  this.consequent.render(code, options);
13144
13608
  this.alternate.render(code, options);
13145
13609
  }
13146
13610
  else {
13611
+ const usedBranch = this.getUsedBranch();
13147
13612
  const colonPos = findFirstOccurrenceOutsideComment(code.original, ':', this.consequent.end);
13148
13613
  const inclusionStart = findNonWhiteSpace(code.original, (this.consequent.included
13149
13614
  ? findFirstOccurrenceOutsideComment(code.original, '?', this.test.end)
@@ -13175,6 +13640,8 @@ class ConditionalExpression extends NodeBase {
13175
13640
  : (this.usedBranch = testValue ? this.consequent : this.alternate);
13176
13641
  }
13177
13642
  }
13643
+ ConditionalExpression.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
13644
+ ConditionalExpression.prototype.applyDeoptimizations = doNotDeoptimize;
13178
13645
 
13179
13646
  class ContinueStatement extends NodeBase {
13180
13647
  hasEffects(context) {
@@ -13194,7 +13661,7 @@ class ContinueStatement extends NodeBase {
13194
13661
  include(context) {
13195
13662
  this.included = true;
13196
13663
  if (this.label) {
13197
- this.label.include();
13664
+ this.label.include(context);
13198
13665
  context.includedLabels.add(this.label.name);
13199
13666
  }
13200
13667
  else {
@@ -13203,12 +13670,15 @@ class ContinueStatement extends NodeBase {
13203
13670
  context.brokenFlow = true;
13204
13671
  }
13205
13672
  }
13673
+ ContinueStatement.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
13674
+ ContinueStatement.prototype.applyDeoptimizations = doNotDeoptimize;
13206
13675
 
13207
13676
  class DebuggerStatement extends NodeBase {
13208
13677
  hasEffects() {
13209
13678
  return true;
13210
13679
  }
13211
13680
  }
13681
+ DebuggerStatement.prototype.includeNode = onlyIncludeSelf;
13212
13682
 
13213
13683
  class Decorator extends NodeBase {
13214
13684
  hasEffects(context) {
@@ -13216,6 +13686,7 @@ class Decorator extends NodeBase {
13216
13686
  this.expression.hasEffectsOnInteractionAtPath(EMPTY_PATH, NODE_INTERACTION_UNKNOWN_CALL, context));
13217
13687
  }
13218
13688
  }
13689
+ Decorator.prototype.includeNode = onlyIncludeSelf;
13219
13690
 
13220
13691
  function hasLoopBodyEffects(context, body) {
13221
13692
  const { brokenFlow, hasBreak, hasContinue, ignore } = context;
@@ -13255,12 +13726,15 @@ class DoWhileStatement extends NodeBase {
13255
13726
  includeLoopBody(context, this.body, includeChildrenRecursively);
13256
13727
  }
13257
13728
  }
13729
+ DoWhileStatement.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
13730
+ DoWhileStatement.prototype.applyDeoptimizations = doNotDeoptimize;
13258
13731
 
13259
13732
  class EmptyStatement extends NodeBase {
13260
13733
  hasEffects() {
13261
13734
  return false;
13262
13735
  }
13263
13736
  }
13737
+ EmptyStatement.prototype.includeNode = onlyIncludeSelf;
13264
13738
 
13265
13739
  class ExportAllDeclaration extends NodeBase {
13266
13740
  hasEffects() {
@@ -13273,9 +13747,10 @@ class ExportAllDeclaration extends NodeBase {
13273
13747
  render(code, _options, nodeRenderOptions) {
13274
13748
  code.remove(nodeRenderOptions.start, nodeRenderOptions.end);
13275
13749
  }
13276
- applyDeoptimizations() { }
13277
13750
  }
13278
13751
  ExportAllDeclaration.prototype.needsBoundaries = true;
13752
+ ExportAllDeclaration.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
13753
+ ExportAllDeclaration.prototype.applyDeoptimizations = doNotDeoptimize;
13279
13754
 
13280
13755
  class ExportNamedDeclaration extends NodeBase {
13281
13756
  bind() {
@@ -13302,13 +13777,15 @@ class ExportNamedDeclaration extends NodeBase {
13302
13777
  this.declaration.render(code, options, { end, start });
13303
13778
  }
13304
13779
  }
13305
- applyDeoptimizations() { }
13306
13780
  }
13307
13781
  ExportNamedDeclaration.prototype.needsBoundaries = true;
13782
+ ExportNamedDeclaration.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
13783
+ ExportNamedDeclaration.prototype.applyDeoptimizations = doNotDeoptimize;
13308
13784
 
13309
13785
  class ExportSpecifier extends NodeBase {
13310
- applyDeoptimizations() { }
13311
13786
  }
13787
+ ExportSpecifier.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
13788
+ ExportSpecifier.prototype.applyDeoptimizations = doNotDeoptimize;
13312
13789
 
13313
13790
  class ForInStatement extends NodeBase {
13314
13791
  createScope(parentScope) {
@@ -13326,11 +13803,18 @@ class ForInStatement extends NodeBase {
13326
13803
  const { body, deoptimized, left, right } = this;
13327
13804
  if (!deoptimized)
13328
13805
  this.applyDeoptimizations();
13329
- this.included = true;
13806
+ if (!this.included)
13807
+ this.includeNode(context);
13330
13808
  left.includeAsAssignmentTarget(context, includeChildrenRecursively || true, false);
13331
13809
  right.include(context, includeChildrenRecursively);
13332
13810
  includeLoopBody(context, body, includeChildrenRecursively);
13333
13811
  }
13812
+ includeNode(context) {
13813
+ this.included = true;
13814
+ if (!this.deoptimized)
13815
+ this.applyDeoptimizations();
13816
+ this.right.includePath(UNKNOWN_PATH, context);
13817
+ }
13334
13818
  initialise() {
13335
13819
  super.initialise();
13336
13820
  this.left.setAssignedValue(UNKNOWN_EXPRESSION);
@@ -13371,11 +13855,18 @@ class ForOfStatement extends NodeBase {
13371
13855
  const { body, deoptimized, left, right } = this;
13372
13856
  if (!deoptimized)
13373
13857
  this.applyDeoptimizations();
13374
- this.included = true;
13858
+ if (!this.included)
13859
+ this.includeNode(context);
13375
13860
  left.includeAsAssignmentTarget(context, includeChildrenRecursively || true, false);
13376
13861
  right.include(context, includeChildrenRecursively);
13377
13862
  includeLoopBody(context, body, includeChildrenRecursively);
13378
13863
  }
13864
+ includeNode(context) {
13865
+ this.included = true;
13866
+ if (!this.deoptimized)
13867
+ this.applyDeoptimizations();
13868
+ this.right.includePath(UNKNOWN_PATH, context);
13869
+ }
13379
13870
  initialise() {
13380
13871
  super.initialise();
13381
13872
  this.left.setAssignedValue(UNKNOWN_EXPRESSION);
@@ -13411,7 +13902,9 @@ class ForStatement extends NodeBase {
13411
13902
  }
13412
13903
  include(context, includeChildrenRecursively) {
13413
13904
  this.included = true;
13414
- this.init?.include(context, includeChildrenRecursively, { asSingleStatement: true });
13905
+ this.init?.include(context, includeChildrenRecursively, {
13906
+ asSingleStatement: true
13907
+ });
13415
13908
  this.test?.include(context, includeChildrenRecursively);
13416
13909
  this.update?.include(context, includeChildrenRecursively);
13417
13910
  includeLoopBody(context, this.body, includeChildrenRecursively);
@@ -13423,6 +13916,8 @@ class ForStatement extends NodeBase {
13423
13916
  this.body.render(code, options);
13424
13917
  }
13425
13918
  }
13919
+ ForStatement.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
13920
+ ForStatement.prototype.applyDeoptimizations = doNotDeoptimize;
13426
13921
 
13427
13922
  class FunctionExpression extends FunctionNode {
13428
13923
  createScope(parentScope) {
@@ -13454,9 +13949,9 @@ class TrackingScope extends BlockScope {
13454
13949
  super(...arguments);
13455
13950
  this.hoistedDeclarations = [];
13456
13951
  }
13457
- addDeclaration(identifier, context, init, kind) {
13952
+ addDeclaration(identifier, context, init, destructuredInitPath, kind) {
13458
13953
  this.hoistedDeclarations.push(identifier);
13459
- return super.addDeclaration(identifier, context, init, kind);
13954
+ return super.addDeclaration(identifier, context, init, destructuredInitPath, kind);
13460
13955
  }
13461
13956
  }
13462
13957
 
@@ -13555,7 +14050,6 @@ class IfStatement extends NodeBase {
13555
14050
  }
13556
14051
  this.renderHoistedDeclarations(hoistedDeclarations, code, getPropertyAccess);
13557
14052
  }
13558
- applyDeoptimizations() { }
13559
14053
  getTestValue() {
13560
14054
  if (this.testValue === unset) {
13561
14055
  return (this.testValue = this.test.getLiteralValueAtPath(EMPTY_PATH, SHARED_RECURSION_TRACKER, this));
@@ -13624,6 +14118,8 @@ class IfStatement extends NodeBase {
13624
14118
  return false;
13625
14119
  }
13626
14120
  }
14121
+ IfStatement.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
14122
+ IfStatement.prototype.applyDeoptimizations = doNotDeoptimize;
13627
14123
 
13628
14124
  class ImportAttribute extends NodeBase {
13629
14125
  }
@@ -13641,13 +14137,15 @@ class ImportDeclaration extends NodeBase {
13641
14137
  render(code, _options, nodeRenderOptions) {
13642
14138
  code.remove(nodeRenderOptions.start, nodeRenderOptions.end);
13643
14139
  }
13644
- applyDeoptimizations() { }
13645
14140
  }
13646
14141
  ImportDeclaration.prototype.needsBoundaries = true;
14142
+ ImportDeclaration.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
14143
+ ImportDeclaration.prototype.applyDeoptimizations = doNotDeoptimize;
13647
14144
 
13648
14145
  class ImportDefaultSpecifier extends NodeBase {
13649
- applyDeoptimizations() { }
13650
14146
  }
14147
+ ImportDefaultSpecifier.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
14148
+ ImportDefaultSpecifier.prototype.applyDeoptimizations = doNotDeoptimize;
13651
14149
 
13652
14150
  function isReassignedExportsMember(variable, exportNamesByVariable) {
13653
14151
  return (variable.renderBaseName !== null && exportNamesByVariable.has(variable) && variable.isReassigned);
@@ -13656,28 +14154,33 @@ function isReassignedExportsMember(variable, exportNamesByVariable) {
13656
14154
  class VariableDeclarator extends NodeBase {
13657
14155
  declareDeclarator(kind, isUsingDeclaration) {
13658
14156
  this.isUsingDeclaration = isUsingDeclaration;
13659
- this.id.declare(kind, this.init || UNDEFINED_EXPRESSION);
14157
+ this.id.declare(kind, EMPTY_PATH, this.init || UNDEFINED_EXPRESSION);
13660
14158
  }
13661
14159
  deoptimizePath(path) {
13662
14160
  this.id.deoptimizePath(path);
13663
14161
  }
13664
14162
  hasEffects(context) {
13665
- if (!this.deoptimized)
13666
- this.applyDeoptimizations();
13667
14163
  const initEffect = this.init?.hasEffects(context);
13668
14164
  this.id.markDeclarationReached();
13669
- return initEffect || this.id.hasEffects(context) || this.isUsingDeclaration;
14165
+ return (initEffect ||
14166
+ this.isUsingDeclaration ||
14167
+ this.id.hasEffects(context) ||
14168
+ (this.scope.context.options.treeshake
14169
+ .propertyReadSideEffects &&
14170
+ this.id.hasEffectsWhenDestructuring(context, EMPTY_PATH, this.init || UNDEFINED_EXPRESSION)));
13670
14171
  }
13671
14172
  include(context, includeChildrenRecursively) {
13672
- const { deoptimized, id, init } = this;
13673
- if (!deoptimized)
13674
- this.applyDeoptimizations();
13675
- this.included = true;
14173
+ const { id, init } = this;
14174
+ if (!this.included)
14175
+ this.includeNode();
13676
14176
  init?.include(context, includeChildrenRecursively);
13677
14177
  id.markDeclarationReached();
13678
- if (includeChildrenRecursively || id.shouldBeIncluded(context)) {
14178
+ if (includeChildrenRecursively) {
13679
14179
  id.include(context, includeChildrenRecursively);
13680
14180
  }
14181
+ else {
14182
+ id.includeDestructuredIfNecessary(context, EMPTY_PATH, init || UNDEFINED_EXPRESSION);
14183
+ }
13681
14184
  }
13682
14185
  removeAnnotations(code) {
13683
14186
  this.init?.removeAnnotations(code);
@@ -13707,8 +14210,8 @@ class VariableDeclarator extends NodeBase {
13707
14210
  code.appendLeft(end, `${_}=${_}void 0`);
13708
14211
  }
13709
14212
  }
13710
- applyDeoptimizations() {
13711
- this.deoptimized = true;
14213
+ includeNode() {
14214
+ this.included = true;
13712
14215
  const { id, init } = this;
13713
14216
  if (init && id instanceof Identifier && init instanceof ClassExpression && !init.id) {
13714
14217
  const { name, variable } = id;
@@ -13720,11 +14223,14 @@ class VariableDeclarator extends NodeBase {
13720
14223
  }
13721
14224
  }
13722
14225
  }
14226
+ VariableDeclarator.prototype.applyDeoptimizations = doNotDeoptimize;
13723
14227
 
13724
14228
  class ImportExpression extends NodeBase {
13725
14229
  constructor() {
13726
14230
  super(...arguments);
13727
14231
  this.inlineNamespace = null;
14232
+ this.hasUnknownAccessedKey = false;
14233
+ this.accessedPropKey = new Set();
13728
14234
  this.attributes = null;
13729
14235
  this.mechanism = null;
13730
14236
  this.namespaceExportName = undefined;
@@ -13757,12 +14263,15 @@ class ImportExpression extends NodeBase {
13757
14263
  if (parent2 instanceof ExpressionStatement) {
13758
14264
  return parseAst_js.EMPTY_ARRAY;
13759
14265
  }
13760
- // Case 1: const { foo } = await import('bar')
14266
+ // Case 1: const { foo } / module = await import('bar')
13761
14267
  if (parent2 instanceof VariableDeclarator) {
13762
14268
  const declaration = parent2.id;
13763
- return declaration instanceof ObjectPattern
13764
- ? getDeterministicObjectDestructure(declaration)
13765
- : undefined;
14269
+ if (declaration instanceof Identifier) {
14270
+ return this.hasUnknownAccessedKey ? undefined : [...this.accessedPropKey];
14271
+ }
14272
+ if (declaration instanceof ObjectPattern) {
14273
+ return getDeterministicObjectDestructure(declaration);
14274
+ }
13766
14275
  }
13767
14276
  // Case 2: (await import('bar')).foo
13768
14277
  if (parent2 instanceof MemberExpression) {
@@ -13812,13 +14321,30 @@ class ImportExpression extends NodeBase {
13812
14321
  return true;
13813
14322
  }
13814
14323
  include(context, includeChildrenRecursively) {
13815
- if (!this.included) {
13816
- this.included = true;
13817
- this.scope.context.includeDynamicImport(this);
13818
- this.scope.addAccessedDynamicImport(this);
13819
- }
14324
+ if (!this.included)
14325
+ this.includeNode();
13820
14326
  this.source.include(context, includeChildrenRecursively);
13821
14327
  }
14328
+ includeNode() {
14329
+ this.included = true;
14330
+ this.scope.context.includeDynamicImport(this);
14331
+ this.scope.addAccessedDynamicImport(this);
14332
+ }
14333
+ includePath(path) {
14334
+ if (!this.included)
14335
+ this.includeNode();
14336
+ // Technically, this is not correct as dynamic imports return a Promise.
14337
+ if (this.hasUnknownAccessedKey)
14338
+ return;
14339
+ if (path[0] === UnknownKey) {
14340
+ this.hasUnknownAccessedKey = true;
14341
+ }
14342
+ else if (typeof path[0] === 'string') {
14343
+ this.accessedPropKey.add(path[0]);
14344
+ }
14345
+ // Update included paths
14346
+ this.scope.context.includeDynamicImport(this);
14347
+ }
13822
14348
  initialise() {
13823
14349
  super.initialise();
13824
14350
  this.scope.context.addDynamicImport(this);
@@ -13887,7 +14413,6 @@ class ImportExpression extends NodeBase {
13887
14413
  setInternalResolution(inlineNamespace) {
13888
14414
  this.inlineNamespace = inlineNamespace;
13889
14415
  }
13890
- applyDeoptimizations() { }
13891
14416
  getDynamicImportMechanismAndHelper(resolution, exportMode, { compact, dynamicImportInCjs, format, generatedCode: { arrowFunctions }, interop }, { _, getDirectReturnFunction, getDirectReturnIifeLeft }, pluginDriver) {
13892
14417
  const mechanism = pluginDriver.hookFirstSync('renderDynamicImport', [
13893
14418
  {
@@ -13977,6 +14502,7 @@ class ImportExpression extends NodeBase {
13977
14502
  return { helper: null, mechanism: null };
13978
14503
  }
13979
14504
  }
14505
+ ImportExpression.prototype.applyDeoptimizations = doNotDeoptimize;
13980
14506
  function getInteropHelper(resolution, exportMode, interop) {
13981
14507
  return exportMode === 'external'
13982
14508
  ? namespaceInteropHelpersByInteropType[interop(resolution instanceof ExternalModule ? resolution.id : null)]
@@ -14000,12 +14526,14 @@ function getDeterministicObjectDestructure(objectPattern) {
14000
14526
  }
14001
14527
 
14002
14528
  class ImportNamespaceSpecifier extends NodeBase {
14003
- applyDeoptimizations() { }
14004
14529
  }
14530
+ ImportNamespaceSpecifier.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
14531
+ ImportNamespaceSpecifier.prototype.applyDeoptimizations = doNotDeoptimize;
14005
14532
 
14006
14533
  class ImportSpecifier extends NodeBase {
14007
- applyDeoptimizations() { }
14008
14534
  }
14535
+ ImportSpecifier.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
14536
+ ImportSpecifier.prototype.applyDeoptimizations = doNotDeoptimize;
14009
14537
 
14010
14538
  class JSXIdentifier extends IdentifierBase {
14011
14539
  constructor() {
@@ -14022,6 +14550,29 @@ class JSXIdentifier extends IdentifierBase {
14022
14550
  this.isNativeElement = true;
14023
14551
  }
14024
14552
  }
14553
+ include(context) {
14554
+ if (!this.included)
14555
+ this.includeNode(context);
14556
+ }
14557
+ includeNode(context) {
14558
+ this.included = true;
14559
+ if (!this.deoptimized)
14560
+ this.applyDeoptimizations();
14561
+ if (this.variable !== null) {
14562
+ this.scope.context.includeVariableInModule(this.variable, EMPTY_PATH, context);
14563
+ }
14564
+ }
14565
+ includePath(path, context) {
14566
+ if (!this.included) {
14567
+ this.included = true;
14568
+ if (this.variable !== null) {
14569
+ this.scope.context.includeVariableInModule(this.variable, path, context);
14570
+ }
14571
+ }
14572
+ else if (path.length > 0) {
14573
+ this.variable?.includePath(path, context);
14574
+ }
14575
+ }
14025
14576
  render(code, { snippets: { getPropertyAccess }, useOriginalName }) {
14026
14577
  if (this.variable) {
14027
14578
  const name = this.variable.getName(getPropertyAccess, useOriginalName);
@@ -14083,6 +14634,7 @@ class JSXAttribute extends NodeBase {
14083
14634
  }
14084
14635
  }
14085
14636
  }
14637
+ JSXAttribute.prototype.includeNode = onlyIncludeSelf;
14086
14638
 
14087
14639
  class JSXClosingBase extends NodeBase {
14088
14640
  render(code, options) {
@@ -14095,6 +14647,7 @@ class JSXClosingBase extends NodeBase {
14095
14647
  }
14096
14648
  }
14097
14649
  }
14650
+ JSXClosingBase.prototype.includeNode = onlyIncludeSelf;
14098
14651
 
14099
14652
  class JSXClosingElement extends JSXClosingBase {
14100
14653
  }
@@ -14115,8 +14668,15 @@ class JSXSpreadAttribute extends NodeBase {
14115
14668
 
14116
14669
  class JSXEmptyExpression extends NodeBase {
14117
14670
  }
14671
+ JSXEmptyExpression.prototype.includeNode = onlyIncludeSelf;
14118
14672
 
14119
14673
  class JSXExpressionContainer extends NodeBase {
14674
+ includeNode(context) {
14675
+ this.included = true;
14676
+ if (!this.deoptimized)
14677
+ this.applyDeoptimizations();
14678
+ this.expression.includePath(UNKNOWN_PATH, context);
14679
+ }
14120
14680
  render(code, options) {
14121
14681
  const { mode } = this.scope.context.options.jsx;
14122
14682
  if (mode !== 'preserve') {
@@ -14137,7 +14697,7 @@ function getRenderedJsxChildren(children) {
14137
14697
  return renderedChildren;
14138
14698
  }
14139
14699
 
14140
- function getAndIncludeFactoryVariable(factory, preserve, importSource, node) {
14700
+ function getAndIncludeFactoryVariable(factory, preserve, importSource, node, context) {
14141
14701
  const [baseName, nestedName] = factory.split('.');
14142
14702
  let factoryVariable;
14143
14703
  if (importSource) {
@@ -14145,7 +14705,7 @@ function getAndIncludeFactoryVariable(factory, preserve, importSource, node) {
14145
14705
  if (preserve) {
14146
14706
  // This pretends we are accessing an included global variable of the same name
14147
14707
  const globalVariable = node.scope.findGlobal(baseName);
14148
- globalVariable.include();
14708
+ globalVariable.includePath(UNKNOWN_PATH, context);
14149
14709
  // This excludes this variable from renaming
14150
14710
  factoryVariable.globalName = baseName;
14151
14711
  }
@@ -14153,7 +14713,7 @@ function getAndIncludeFactoryVariable(factory, preserve, importSource, node) {
14153
14713
  else {
14154
14714
  factoryVariable = node.scope.findGlobal(baseName);
14155
14715
  }
14156
- node.scope.context.includeVariableInModule(factoryVariable);
14716
+ node.scope.context.includeVariableInModule(factoryVariable, UNKNOWN_PATH, context);
14157
14717
  if (factoryVariable instanceof LocalVariable) {
14158
14718
  factoryVariable.consolidateInitializers();
14159
14719
  factoryVariable.addUsedPlace(node);
@@ -14176,16 +14736,20 @@ class JSXElementBase extends NodeBase {
14176
14736
  }
14177
14737
  }
14178
14738
  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
- }
14739
+ if (!this.included)
14740
+ this.includeNode(context);
14741
+ for (const child of this.children) {
14742
+ child.include(context, includeChildrenRecursively);
14743
+ }
14744
+ }
14745
+ includeNode(context) {
14746
+ this.included = true;
14747
+ const { factory, importSource, mode } = this.jsxMode;
14748
+ if (factory) {
14749
+ this.factory = factory;
14750
+ this.factoryVariable = getAndIncludeFactoryVariable(factory, mode === 'preserve', importSource, this, context);
14185
14751
  }
14186
- super.include(context, includeChildrenRecursively);
14187
14752
  }
14188
- applyDeoptimizations() { }
14189
14753
  getRenderingMode() {
14190
14754
  const jsx = this.scope.context.options.jsx;
14191
14755
  const { mode, factory, importSource } = jsx;
@@ -14223,8 +14787,14 @@ class JSXElementBase extends NodeBase {
14223
14787
  return { childrenEnd, firstChild, hasMultipleChildren };
14224
14788
  }
14225
14789
  }
14790
+ JSXElementBase.prototype.applyDeoptimizations = doNotDeoptimize;
14226
14791
 
14227
14792
  class JSXElement extends JSXElementBase {
14793
+ include(context, includeChildrenRecursively) {
14794
+ super.include(context, includeChildrenRecursively);
14795
+ this.openingElement.include(context, includeChildrenRecursively);
14796
+ this.closingElement?.include(context, includeChildrenRecursively);
14797
+ }
14228
14798
  render(code, options) {
14229
14799
  switch (this.jsxMode.mode) {
14230
14800
  case 'classic': {
@@ -14376,6 +14946,11 @@ class JSXElement extends JSXElementBase {
14376
14946
  }
14377
14947
 
14378
14948
  class JSXFragment extends JSXElementBase {
14949
+ include(context, includeChildrenRecursively) {
14950
+ super.include(context, includeChildrenRecursively);
14951
+ this.openingFragment.include(context, includeChildrenRecursively);
14952
+ this.closingFragment.include(context, includeChildrenRecursively);
14953
+ }
14379
14954
  render(code, options) {
14380
14955
  switch (this.jsxMode.mode) {
14381
14956
  case 'classic': {
@@ -14425,10 +15000,22 @@ class JSXFragment extends JSXElementBase {
14425
15000
  }
14426
15001
 
14427
15002
  class JSXMemberExpression extends NodeBase {
15003
+ includeNode(context) {
15004
+ this.included = true;
15005
+ if (!this.deoptimized)
15006
+ this.applyDeoptimizations();
15007
+ this.object.includePath([this.property.name], context);
15008
+ }
15009
+ includePath(path, context) {
15010
+ if (!this.included)
15011
+ this.includeNode(context);
15012
+ this.object.includePath([this.property.name, ...path], context);
15013
+ }
14428
15014
  }
14429
15015
 
14430
15016
  class JSXNamespacedName extends NodeBase {
14431
15017
  }
15018
+ JSXNamespacedName.prototype.includeNode = onlyIncludeSelf;
14432
15019
 
14433
15020
  class JSXOpeningElement extends NodeBase {
14434
15021
  render(code, options, { jsxMode = this.scope.context.options.jsx.mode } = {}) {
@@ -14438,6 +15025,7 @@ class JSXOpeningElement extends NodeBase {
14438
15025
  }
14439
15026
  }
14440
15027
  }
15028
+ JSXOpeningElement.prototype.includeNode = onlyIncludeSelf;
14441
15029
 
14442
15030
  class JSXOpeningFragment extends NodeBase {
14443
15031
  constructor() {
@@ -14445,22 +15033,22 @@ class JSXOpeningFragment extends NodeBase {
14445
15033
  this.fragment = null;
14446
15034
  this.fragmentVariable = null;
14447
15035
  }
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
- }
15036
+ includeNode(context) {
15037
+ this.included = true;
15038
+ if (!this.deoptimized)
15039
+ this.applyDeoptimizations();
15040
+ const jsx = this.scope.context.options.jsx;
15041
+ if (jsx.mode === 'automatic') {
15042
+ this.fragment = 'Fragment';
15043
+ this.fragmentVariable = getAndIncludeFactoryVariable('Fragment', false, jsx.jsxImportSource, this, context);
15044
+ }
15045
+ else {
15046
+ const { fragment, importSource, mode } = jsx;
15047
+ if (fragment != null) {
15048
+ this.fragment = fragment;
15049
+ this.fragmentVariable = getAndIncludeFactoryVariable(fragment, mode === 'preserve', importSource, this, context);
14461
15050
  }
14462
15051
  }
14463
- super.include(context, includeChildrenRecursively);
14464
15052
  }
14465
15053
  render(code, options) {
14466
15054
  const { mode } = this.scope.context.options.jsx;
@@ -14497,6 +15085,7 @@ class JSXText extends NodeBase {
14497
15085
  }
14498
15086
  }
14499
15087
  }
15088
+ JSXText.prototype.includeNode = onlyIncludeSelf;
14500
15089
 
14501
15090
  class LabeledStatement extends NodeBase {
14502
15091
  hasEffects(context) {
@@ -14518,17 +15107,22 @@ class LabeledStatement extends NodeBase {
14518
15107
  return bodyHasEffects;
14519
15108
  }
14520
15109
  include(context, includeChildrenRecursively) {
14521
- this.included = true;
15110
+ if (!this.included)
15111
+ this.includeNode(context);
14522
15112
  const { brokenFlow, includedLabels } = context;
14523
15113
  context.includedLabels = new Set();
14524
15114
  this.body.include(context, includeChildrenRecursively);
14525
15115
  if (includeChildrenRecursively || context.includedLabels.has(this.label.name)) {
14526
- this.label.include();
15116
+ this.label.include(context);
14527
15117
  context.includedLabels.delete(this.label.name);
14528
15118
  context.brokenFlow = brokenFlow;
14529
15119
  }
14530
15120
  context.includedLabels = new Set([...includedLabels, ...context.includedLabels]);
14531
15121
  }
15122
+ includeNode(context) {
15123
+ this.included = true;
15124
+ this.body.includePath(UNKNOWN_PATH, context);
15125
+ }
14532
15126
  render(code, options) {
14533
15127
  if (this.label.included) {
14534
15128
  this.label.render(code, options);
@@ -14539,6 +15133,7 @@ class LabeledStatement extends NodeBase {
14539
15133
  this.body.render(code, options);
14540
15134
  }
14541
15135
  }
15136
+ LabeledStatement.prototype.applyDeoptimizations = doNotDeoptimize;
14542
15137
 
14543
15138
  class LogicalExpression extends NodeBase {
14544
15139
  constructor() {
@@ -14563,6 +15158,10 @@ class LogicalExpression extends NodeBase {
14563
15158
  const unusedBranch = this.usedBranch === this.left ? this.right : this.left;
14564
15159
  this.usedBranch = null;
14565
15160
  unusedBranch.deoptimizePath(UNKNOWN_PATH);
15161
+ if (this.included) {
15162
+ // As we are not tracking inclusions, we just include everything
15163
+ unusedBranch.includePath(UNKNOWN_PATH, createInclusionContext());
15164
+ }
14566
15165
  const { scope: { context }, expressionsToBeDeoptimized } = this;
14567
15166
  this.expressionsToBeDeoptimized = parseAst_js.EMPTY_ARRAY;
14568
15167
  for (const expression of expressionsToBeDeoptimized) {
@@ -14585,23 +15184,25 @@ class LogicalExpression extends NodeBase {
14585
15184
  }
14586
15185
  getLiteralValueAtPath(path, recursionTracker, origin) {
14587
15186
  const usedBranch = this.getUsedBranch();
14588
- if (!usedBranch)
14589
- return UnknownValue;
14590
- this.expressionsToBeDeoptimized.push(origin);
14591
- return usedBranch.getLiteralValueAtPath(path, recursionTracker, origin);
15187
+ if (usedBranch) {
15188
+ this.expressionsToBeDeoptimized.push(origin);
15189
+ return usedBranch.getLiteralValueAtPath(path, recursionTracker, origin);
15190
+ }
15191
+ return UnknownValue;
14592
15192
  }
14593
15193
  getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin) {
14594
15194
  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);
15195
+ if (usedBranch) {
15196
+ this.expressionsToBeDeoptimized.push(origin);
15197
+ return usedBranch.getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin);
15198
+ }
15199
+ return [
15200
+ new MultiExpression([
15201
+ this.left.getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin)[0],
15202
+ this.right.getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin)[0]
15203
+ ]),
15204
+ false
15205
+ ];
14605
15206
  }
14606
15207
  hasEffects(context) {
14607
15208
  if (this.left.hasEffects(context)) {
@@ -14614,18 +15215,18 @@ class LogicalExpression extends NodeBase {
14614
15215
  }
14615
15216
  hasEffectsOnInteractionAtPath(path, interaction, context) {
14616
15217
  const usedBranch = this.getUsedBranch();
14617
- if (!usedBranch) {
14618
- return (this.left.hasEffectsOnInteractionAtPath(path, interaction, context) ||
14619
- this.right.hasEffectsOnInteractionAtPath(path, interaction, context));
15218
+ if (usedBranch) {
15219
+ return usedBranch.hasEffectsOnInteractionAtPath(path, interaction, context);
14620
15220
  }
14621
- return usedBranch.hasEffectsOnInteractionAtPath(path, interaction, context);
15221
+ return (this.left.hasEffectsOnInteractionAtPath(path, interaction, context) ||
15222
+ this.right.hasEffectsOnInteractionAtPath(path, interaction, context));
14622
15223
  }
14623
15224
  include(context, includeChildrenRecursively) {
14624
15225
  this.included = true;
14625
15226
  const usedBranch = this.getUsedBranch();
14626
15227
  if (includeChildrenRecursively ||
14627
- (usedBranch === this.right && this.left.shouldBeIncluded(context)) ||
14628
- !usedBranch) {
15228
+ !usedBranch ||
15229
+ (usedBranch === this.right && this.left.shouldBeIncluded(context))) {
14629
15230
  this.left.include(context, includeChildrenRecursively);
14630
15231
  this.right.include(context, includeChildrenRecursively);
14631
15232
  }
@@ -14633,6 +15234,17 @@ class LogicalExpression extends NodeBase {
14633
15234
  usedBranch.include(context, includeChildrenRecursively);
14634
15235
  }
14635
15236
  }
15237
+ includePath(path, context) {
15238
+ this.included = true;
15239
+ const usedBranch = this.getUsedBranch();
15240
+ if (!usedBranch || (usedBranch === this.right && this.left.shouldBeIncluded(context))) {
15241
+ this.left.includePath(path, context);
15242
+ this.right.includePath(path, context);
15243
+ }
15244
+ else {
15245
+ usedBranch.includePath(path, context);
15246
+ }
15247
+ }
14636
15248
  removeAnnotations(code) {
14637
15249
  this.left.removeAnnotations(code);
14638
15250
  }
@@ -14684,6 +15296,8 @@ class LogicalExpression extends NodeBase {
14684
15296
  return this.usedBranch;
14685
15297
  }
14686
15298
  }
15299
+ LogicalExpression.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
15300
+ LogicalExpression.prototype.applyDeoptimizations = doNotDeoptimize;
14687
15301
 
14688
15302
  class NewExpression extends NodeBase {
14689
15303
  hasEffects(context) {
@@ -14703,16 +15317,21 @@ class NewExpression extends NodeBase {
14703
15317
  return path.length > 0 || type !== INTERACTION_ACCESSED;
14704
15318
  }
14705
15319
  include(context, includeChildrenRecursively) {
14706
- if (!this.deoptimized)
14707
- this.applyDeoptimizations();
14708
15320
  if (includeChildrenRecursively) {
14709
15321
  super.include(context, includeChildrenRecursively);
14710
15322
  }
14711
15323
  else {
14712
- this.included = true;
15324
+ if (!this.included)
15325
+ this.includeNode(context);
14713
15326
  this.callee.include(context, false);
14714
15327
  }
14715
- this.callee.includeCallArguments(context, this.arguments);
15328
+ this.callee.includeCallArguments(context, this.interaction);
15329
+ }
15330
+ includeNode(context) {
15331
+ this.included = true;
15332
+ if (!this.deoptimized)
15333
+ this.applyDeoptimizations();
15334
+ this.callee.includePath(UNKNOWN_PATH, context);
14716
15335
  }
14717
15336
  initialise() {
14718
15337
  super.initialise();
@@ -14741,6 +15360,7 @@ class ObjectExpression extends NodeBase {
14741
15360
  constructor() {
14742
15361
  super(...arguments);
14743
15362
  this.objectEntity = null;
15363
+ this.protoProp = null;
14744
15364
  }
14745
15365
  deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
14746
15366
  this.getObjectEntity().deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker);
@@ -14760,15 +15380,43 @@ class ObjectExpression extends NodeBase {
14760
15380
  hasEffectsOnInteractionAtPath(path, interaction, context) {
14761
15381
  return this.getObjectEntity().hasEffectsOnInteractionAtPath(path, interaction, context);
14762
15382
  }
15383
+ include(context, includeChildrenRecursively) {
15384
+ if (!this.included)
15385
+ this.includeNode(context);
15386
+ this.getObjectEntity().include(context, includeChildrenRecursively);
15387
+ this.protoProp?.include(context, includeChildrenRecursively);
15388
+ }
15389
+ includeNode(context) {
15390
+ this.included = true;
15391
+ this.protoProp?.includePath(UNKNOWN_PATH, context);
15392
+ }
15393
+ includePath(path, context) {
15394
+ if (!this.included)
15395
+ this.includeNode(context);
15396
+ this.getObjectEntity().includePath(path, context);
15397
+ }
14763
15398
  render(code, options, { renderedSurroundingElement } = parseAst_js.BLANK) {
14764
- super.render(code, options);
14765
15399
  if (renderedSurroundingElement === parseAst_js.ExpressionStatement ||
14766
15400
  renderedSurroundingElement === parseAst_js.ArrowFunctionExpression) {
14767
15401
  code.appendRight(this.start, '(');
14768
15402
  code.prependLeft(this.end, ')');
14769
15403
  }
15404
+ if (this.properties.length > 0) {
15405
+ const separatedNodes = getCommaSeparatedNodesWithBoundaries(this.properties, code, this.start + 1, this.end - 1);
15406
+ let lastSeparatorPos = null;
15407
+ for (const { node, separator, start, end } of separatedNodes) {
15408
+ if (!node.included) {
15409
+ treeshakeNode(node, code, start, end);
15410
+ continue;
15411
+ }
15412
+ lastSeparatorPos = separator;
15413
+ node.render(code, options);
15414
+ }
15415
+ if (lastSeparatorPos) {
15416
+ code.remove(lastSeparatorPos, this.end - 1);
15417
+ }
15418
+ }
14770
15419
  }
14771
- applyDeoptimizations() { }
14772
15420
  getObjectEntity() {
14773
15421
  if (this.objectEntity !== null) {
14774
15422
  return this.objectEntity;
@@ -14797,6 +15445,7 @@ class ObjectExpression extends NodeBase {
14797
15445
  ? property.key.name
14798
15446
  : String(property.key.value);
14799
15447
  if (key === '__proto__' && property.kind === 'init') {
15448
+ this.protoProp = property;
14800
15449
  prototype =
14801
15450
  property.value instanceof Literal && property.value.value === null
14802
15451
  ? null
@@ -14809,6 +15458,7 @@ class ObjectExpression extends NodeBase {
14809
15458
  return (this.objectEntity = new ObjectEntity(properties, prototype));
14810
15459
  }
14811
15460
  }
15461
+ ObjectExpression.prototype.applyDeoptimizations = doNotDeoptimize;
14812
15462
 
14813
15463
  class PanicError extends NodeBase {
14814
15464
  initialise() {
@@ -14835,6 +15485,7 @@ class ParseError extends NodeBase {
14835
15485
 
14836
15486
  class PrivateIdentifier extends NodeBase {
14837
15487
  }
15488
+ PrivateIdentifier.prototype.includeNode = onlyIncludeSelf;
14838
15489
 
14839
15490
  class Program extends NodeBase {
14840
15491
  constructor() {
@@ -14902,14 +15553,11 @@ class Program extends NodeBase {
14902
15553
  super.render(code, options);
14903
15554
  }
14904
15555
  }
14905
- applyDeoptimizations() { }
14906
15556
  }
15557
+ Program.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
15558
+ Program.prototype.applyDeoptimizations = doNotDeoptimize;
14907
15559
 
14908
15560
  class Property extends MethodBase {
14909
- constructor() {
14910
- super(...arguments);
14911
- this.declarationInit = null;
14912
- }
14913
15561
  //declare method: boolean;
14914
15562
  get method() {
14915
15563
  return isFlagSet(this.flags, 262144 /* Flag.method */);
@@ -14924,17 +15572,41 @@ class Property extends MethodBase {
14924
15572
  set shorthand(value) {
14925
15573
  this.flags = setFlag(this.flags, 524288 /* Flag.shorthand */, value);
14926
15574
  }
14927
- declare(kind, init) {
14928
- this.declarationInit = init;
14929
- return this.value.declare(kind, UNKNOWN_EXPRESSION);
15575
+ declare(kind, destructuredInitPath, init) {
15576
+ return this.value.declare(kind, this.getPathInProperty(destructuredInitPath), init);
15577
+ }
15578
+ deoptimizeAssignment(destructuredInitPath, init) {
15579
+ this.value.deoptimizeAssignment?.(this.getPathInProperty(destructuredInitPath), init);
14930
15580
  }
14931
15581
  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));
15582
+ return this.key.hasEffects(context) || this.value.hasEffects(context);
15583
+ }
15584
+ hasEffectsWhenDestructuring(context, destructuredInitPath, init) {
15585
+ return this.value.hasEffectsWhenDestructuring?.(context, this.getPathInProperty(destructuredInitPath), init);
15586
+ }
15587
+ includeDestructuredIfNecessary(context, destructuredInitPath, init) {
15588
+ const path = this.getPathInProperty(destructuredInitPath);
15589
+ let included = this.value.includeDestructuredIfNecessary(context, path, init) ||
15590
+ this.included;
15591
+ if ((included ||= this.key.hasEffects(createHasEffectsContext()))) {
15592
+ this.key.include(context, false);
15593
+ if (!this.value.included) {
15594
+ this.value.included = true;
15595
+ // Unfortunately, we need to include the value again now, so that any
15596
+ // declared variables are properly included.
15597
+ this.value.includeDestructuredIfNecessary(context, path, init);
15598
+ }
15599
+ }
15600
+ return (this.included = included);
15601
+ }
15602
+ include(context, includeChildrenRecursively) {
15603
+ this.included = true;
15604
+ this.key.include(context, includeChildrenRecursively);
15605
+ this.value.include(context, includeChildrenRecursively);
15606
+ }
15607
+ includePath(path, context) {
15608
+ this.included = true;
15609
+ this.value.includePath(path, context);
14938
15610
  }
14939
15611
  markDeclarationReached() {
14940
15612
  this.value.markDeclarationReached();
@@ -14945,14 +15617,20 @@ class Property extends MethodBase {
14945
15617
  }
14946
15618
  this.value.render(code, options, { isShorthandProperty: this.shorthand });
14947
15619
  }
14948
- applyDeoptimizations() {
14949
- this.deoptimized = true;
14950
- if (this.declarationInit !== null) {
14951
- this.declarationInit.deoptimizePath([UnknownKey, UnknownKey]);
14952
- this.scope.context.requestTreeshakingPass();
14953
- }
15620
+ getPathInProperty(destructuredInitPath) {
15621
+ return destructuredInitPath.at(-1) === UnknownKey
15622
+ ? destructuredInitPath
15623
+ : // For now, we only consider static paths as we do not know how to
15624
+ // deoptimize the path in the dynamic case.
15625
+ this.computed
15626
+ ? [...destructuredInitPath, UnknownKey]
15627
+ : this.key instanceof Identifier
15628
+ ? [...destructuredInitPath, this.key.name]
15629
+ : [...destructuredInitPath, String(this.key.value)];
14954
15630
  }
14955
15631
  }
15632
+ Property.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
15633
+ Property.prototype.applyDeoptimizations = doNotDeoptimize;
14956
15634
 
14957
15635
  class PropertyDefinition extends NodeBase {
14958
15636
  get computed() {
@@ -14985,8 +15663,15 @@ class PropertyDefinition extends NodeBase {
14985
15663
  hasEffectsOnInteractionAtPath(path, interaction, context) {
14986
15664
  return !this.value || this.value.hasEffectsOnInteractionAtPath(path, interaction, context);
14987
15665
  }
14988
- applyDeoptimizations() { }
15666
+ includeNode(context) {
15667
+ this.included = true;
15668
+ this.value?.includePath(UNKNOWN_PATH, context);
15669
+ for (const decorator of this.decorators) {
15670
+ decorator.includePath(UNKNOWN_PATH, context);
15671
+ }
15672
+ }
14989
15673
  }
15674
+ PropertyDefinition.prototype.applyDeoptimizations = doNotDeoptimize;
14990
15675
 
14991
15676
  class ReturnStatement extends NodeBase {
14992
15677
  hasEffects(context) {
@@ -14996,10 +15681,15 @@ class ReturnStatement extends NodeBase {
14996
15681
  return false;
14997
15682
  }
14998
15683
  include(context, includeChildrenRecursively) {
14999
- this.included = true;
15684
+ if (!this.included)
15685
+ this.includeNode(context);
15000
15686
  this.argument?.include(context, includeChildrenRecursively);
15001
15687
  context.brokenFlow = true;
15002
15688
  }
15689
+ includeNode(context) {
15690
+ this.included = true;
15691
+ this.argument?.includePath(UNKNOWN_PATH, context);
15692
+ }
15003
15693
  initialise() {
15004
15694
  super.initialise();
15005
15695
  this.scope.addReturnExpression(this.argument || UNKNOWN_EXPRESSION);
@@ -15013,6 +15703,7 @@ class ReturnStatement extends NodeBase {
15013
15703
  }
15014
15704
  }
15015
15705
  }
15706
+ ReturnStatement.prototype.applyDeoptimizations = doNotDeoptimize;
15016
15707
 
15017
15708
  class SequenceExpression extends NodeBase {
15018
15709
  deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
@@ -15040,10 +15731,15 @@ class SequenceExpression extends NodeBase {
15040
15731
  for (const expression of this.expressions) {
15041
15732
  if (includeChildrenRecursively ||
15042
15733
  (expression === lastExpression && !(this.parent instanceof ExpressionStatement)) ||
15043
- expression.shouldBeIncluded(context))
15734
+ expression.shouldBeIncluded(context)) {
15044
15735
  expression.include(context, includeChildrenRecursively);
15736
+ }
15045
15737
  }
15046
15738
  }
15739
+ includePath(path, context) {
15740
+ this.included = true;
15741
+ this.expressions[this.expressions.length - 1].includePath(path, context);
15742
+ }
15047
15743
  removeAnnotations(code) {
15048
15744
  this.expressions[0].removeAnnotations(code);
15049
15745
  }
@@ -15078,6 +15774,8 @@ class SequenceExpression extends NodeBase {
15078
15774
  }
15079
15775
  }
15080
15776
  }
15777
+ SequenceExpression.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
15778
+ SequenceExpression.prototype.applyDeoptimizations = doNotDeoptimize;
15081
15779
 
15082
15780
  class Super extends NodeBase {
15083
15781
  bind() {
@@ -15089,11 +15787,15 @@ class Super extends NodeBase {
15089
15787
  deoptimizePath(path) {
15090
15788
  this.variable.deoptimizePath(path);
15091
15789
  }
15092
- include() {
15093
- if (!this.included) {
15094
- this.included = true;
15095
- this.scope.context.includeVariableInModule(this.variable);
15096
- }
15790
+ include(context) {
15791
+ if (!this.included)
15792
+ this.includeNode(context);
15793
+ }
15794
+ includeNode(context) {
15795
+ this.included = true;
15796
+ if (!this.deoptimized)
15797
+ this.applyDeoptimizations();
15798
+ this.scope.context.includeVariableInModule(this.variable, EMPTY_PATH, context);
15097
15799
  }
15098
15800
  }
15099
15801
 
@@ -15134,6 +15836,8 @@ class SwitchCase extends NodeBase {
15134
15836
  }
15135
15837
  }
15136
15838
  SwitchCase.prototype.needsBoundaries = true;
15839
+ SwitchCase.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
15840
+ SwitchCase.prototype.applyDeoptimizations = doNotDeoptimize;
15137
15841
 
15138
15842
  class SwitchStatement extends NodeBase {
15139
15843
  createScope(parentScope) {
@@ -15216,6 +15920,8 @@ class SwitchStatement extends NodeBase {
15216
15920
  }
15217
15921
  }
15218
15922
  }
15923
+ SwitchStatement.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
15924
+ SwitchStatement.prototype.applyDeoptimizations = doNotDeoptimize;
15219
15925
 
15220
15926
  class TaggedTemplateExpression extends CallExpressionBase {
15221
15927
  bind() {
@@ -15239,8 +15945,8 @@ class TaggedTemplateExpression extends CallExpressionBase {
15239
15945
  this.tag.hasEffectsOnInteractionAtPath(EMPTY_PATH, this.interaction, context));
15240
15946
  }
15241
15947
  include(context, includeChildrenRecursively) {
15242
- if (!this.deoptimized)
15243
- this.applyDeoptimizations();
15948
+ if (!this.included)
15949
+ this.includeNode(context);
15244
15950
  if (includeChildrenRecursively) {
15245
15951
  super.include(context, includeChildrenRecursively);
15246
15952
  }
@@ -15249,7 +15955,7 @@ class TaggedTemplateExpression extends CallExpressionBase {
15249
15955
  this.tag.include(context, includeChildrenRecursively);
15250
15956
  this.quasi.include(context, includeChildrenRecursively);
15251
15957
  }
15252
- this.tag.includeCallArguments(context, this.args);
15958
+ this.tag.includeCallArguments(context, this.interaction);
15253
15959
  const [returnExpression] = this.getReturnExpression();
15254
15960
  if (!returnExpression.included) {
15255
15961
  returnExpression.include(context, false);
@@ -15284,6 +15990,7 @@ class TaggedTemplateExpression extends CallExpressionBase {
15284
15990
  return this.returnExpression;
15285
15991
  }
15286
15992
  }
15993
+ TaggedTemplateExpression.prototype.includeNode = onlyIncludeSelf;
15287
15994
 
15288
15995
  class TemplateElement extends NodeBase {
15289
15996
  get tail() {
@@ -15297,15 +16004,13 @@ class TemplateElement extends NodeBase {
15297
16004
  hasEffects() {
15298
16005
  return false;
15299
16006
  }
15300
- include() {
15301
- this.included = true;
15302
- }
15303
16007
  parseNode(esTreeNode) {
15304
16008
  this.value = esTreeNode.value;
15305
16009
  return super.parseNode(esTreeNode);
15306
16010
  }
15307
16011
  render() { }
15308
16012
  }
16013
+ TemplateElement.prototype.includeNode = onlyIncludeSelf;
15309
16014
 
15310
16015
  class TemplateLiteral extends NodeBase {
15311
16016
  deoptimizeArgumentsOnInteractionAtPath() { }
@@ -15330,6 +16035,14 @@ class TemplateLiteral extends NodeBase {
15330
16035
  }
15331
16036
  return true;
15332
16037
  }
16038
+ includeNode(context) {
16039
+ this.included = true;
16040
+ if (!this.deoptimized)
16041
+ this.applyDeoptimizations();
16042
+ for (const node of this.expressions) {
16043
+ node.includePath(UNKNOWN_PATH, context);
16044
+ }
16045
+ }
15333
16046
  render(code, options) {
15334
16047
  code.indentExclusionRanges.push([this.start, this.end]);
15335
16048
  super.render(code, options);
@@ -15339,13 +16052,13 @@ class TemplateLiteral extends NodeBase {
15339
16052
  class ModuleScope extends ChildScope {
15340
16053
  constructor(parent, context) {
15341
16054
  super(parent, context);
15342
- this.variables.set('this', new LocalVariable('this', null, UNDEFINED_EXPRESSION, context, 'other'));
16055
+ this.variables.set('this', new LocalVariable('this', null, UNDEFINED_EXPRESSION, EMPTY_PATH, context, 'other'));
15343
16056
  }
15344
- addDeclaration(identifier, context, init, kind) {
16057
+ addDeclaration(identifier, context, init, destructuredInitPath, kind) {
15345
16058
  if (this.context.module.importDescriptions.has(identifier.name)) {
15346
16059
  context.error(parseAst_js.logRedeclarationError(identifier.name), identifier.start);
15347
16060
  }
15348
- return super.addDeclaration(identifier, context, init, kind);
16061
+ return super.addDeclaration(identifier, context, init, destructuredInitPath, kind);
15349
16062
  }
15350
16063
  addExportDefaultDeclaration(name, exportDefaultDeclaration, context) {
15351
16064
  const variable = new ExportDefaultVariable(name, exportDefaultDeclaration, context);
@@ -15390,10 +16103,23 @@ class ThisExpression extends NodeBase {
15390
16103
  }
15391
16104
  return this.variable.hasEffectsOnInteractionAtPath(path, interaction, context);
15392
16105
  }
15393
- include() {
16106
+ include(context) {
16107
+ if (!this.included)
16108
+ this.includeNode(context);
16109
+ }
16110
+ includeNode(context) {
16111
+ this.included = true;
16112
+ if (!this.deoptimized)
16113
+ this.applyDeoptimizations();
16114
+ this.scope.context.includeVariableInModule(this.variable, EMPTY_PATH, context);
16115
+ }
16116
+ includePath(path, context) {
15394
16117
  if (!this.included) {
15395
16118
  this.included = true;
15396
- this.scope.context.includeVariableInModule(this.variable);
16119
+ this.scope.context.includeVariableInModule(this.variable, path, context);
16120
+ }
16121
+ else if (path.length > 0) {
16122
+ this.variable.includePath(path, context);
15397
16123
  }
15398
16124
  }
15399
16125
  initialise() {
@@ -15421,7 +16147,8 @@ class ThrowStatement extends NodeBase {
15421
16147
  return true;
15422
16148
  }
15423
16149
  include(context, includeChildrenRecursively) {
15424
- this.included = true;
16150
+ if (!this.included)
16151
+ this.includeNode(context);
15425
16152
  this.argument.include(context, includeChildrenRecursively);
15426
16153
  context.brokenFlow = true;
15427
16154
  }
@@ -15432,6 +16159,7 @@ class ThrowStatement extends NodeBase {
15432
16159
  }
15433
16160
  }
15434
16161
  }
16162
+ ThrowStatement.prototype.includeNode = onlyIncludeSelf;
15435
16163
 
15436
16164
  class TryStatement extends NodeBase {
15437
16165
  constructor() {
@@ -15468,6 +16196,8 @@ class TryStatement extends NodeBase {
15468
16196
  this.finalizer?.include(context, includeChildrenRecursively);
15469
16197
  }
15470
16198
  }
16199
+ TryStatement.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
16200
+ TryStatement.prototype.applyDeoptimizations = doNotDeoptimize;
15471
16201
 
15472
16202
  const unaryOperators = {
15473
16203
  '!': value => !value,
@@ -15513,6 +16243,7 @@ class UnaryExpression extends NodeBase {
15513
16243
  }
15514
16244
  }
15515
16245
  }
16246
+ UnaryExpression.prototype.includeNode = onlyIncludeSelf;
15516
16247
 
15517
16248
  class UpdateExpression extends NodeBase {
15518
16249
  hasEffects(context) {
@@ -15524,9 +16255,8 @@ class UpdateExpression extends NodeBase {
15524
16255
  return path.length > 1 || type !== INTERACTION_ACCESSED;
15525
16256
  }
15526
16257
  include(context, includeChildrenRecursively) {
15527
- if (!this.deoptimized)
15528
- this.applyDeoptimizations();
15529
- this.included = true;
16258
+ if (!this.included)
16259
+ this.includeNode(context);
15530
16260
  this.argument.includeAsAssignmentTarget(context, includeChildrenRecursively, true);
15531
16261
  }
15532
16262
  initialise() {
@@ -15565,6 +16295,7 @@ class UpdateExpression extends NodeBase {
15565
16295
  this.scope.context.requestTreeshakingPass();
15566
16296
  }
15567
16297
  }
16298
+ UpdateExpression.prototype.includeNode = onlyIncludeSelf;
15568
16299
 
15569
16300
  function areAllDeclarationsIncludedAndNotExported(declarations, exportNamesByVariable) {
15570
16301
  for (const declarator of declarations) {
@@ -15595,8 +16326,9 @@ class VariableDeclaration extends NodeBase {
15595
16326
  include(context, includeChildrenRecursively, { asSingleStatement } = parseAst_js.BLANK) {
15596
16327
  this.included = true;
15597
16328
  for (const declarator of this.declarations) {
15598
- if (includeChildrenRecursively || declarator.shouldBeIncluded(context))
16329
+ if (includeChildrenRecursively || declarator.shouldBeIncluded(context)) {
15599
16330
  declarator.include(context, includeChildrenRecursively);
16331
+ }
15600
16332
  const { id, init } = declarator;
15601
16333
  if (asSingleStatement) {
15602
16334
  id.include(context, includeChildrenRecursively);
@@ -15634,7 +16366,6 @@ class VariableDeclaration extends NodeBase {
15634
16366
  this.renderReplacedDeclarations(code, options);
15635
16367
  }
15636
16368
  }
15637
- applyDeoptimizations() { }
15638
16369
  renderDeclarationEnd(code, separatorString, lastSeparatorPos, actualContentEnd, renderedContentEnd, systemPatternExports, options) {
15639
16370
  if (code.original.charCodeAt(this.end - 1) === 59 /*";"*/) {
15640
16371
  code.remove(this.end - 1, this.end);
@@ -15677,8 +16408,7 @@ class VariableDeclaration extends NodeBase {
15677
16408
  const singleSystemExport = gatherSystemExportsAndGetSingleExport(separatedNodes, options, aggregatedSystemExports);
15678
16409
  for (const { node, start, separator, contentEnd, end } of separatedNodes) {
15679
16410
  if (!node.included) {
15680
- code.remove(start, end);
15681
- node.removeAnnotations(code);
16411
+ treeshakeNode(node, code, start, end);
15682
16412
  continue;
15683
16413
  }
15684
16414
  node.render(code, options);
@@ -15748,6 +16478,8 @@ function gatherSystemExportsAndGetSingleExport(separatedNodes, options, aggregat
15748
16478
  }
15749
16479
  return singleSystemExport;
15750
16480
  }
16481
+ VariableDeclaration.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
16482
+ VariableDeclaration.prototype.applyDeoptimizations = doNotDeoptimize;
15751
16483
 
15752
16484
  class WhileStatement extends NodeBase {
15753
16485
  hasEffects(context) {
@@ -15761,13 +16493,25 @@ class WhileStatement extends NodeBase {
15761
16493
  includeLoopBody(context, this.body, includeChildrenRecursively);
15762
16494
  }
15763
16495
  }
16496
+ WhileStatement.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
16497
+ WhileStatement.prototype.applyDeoptimizations = doNotDeoptimize;
15764
16498
 
15765
16499
  class YieldExpression extends NodeBase {
16500
+ applyDeoptimizations() {
16501
+ this.deoptimized = true;
16502
+ this.argument?.deoptimizePath(UNKNOWN_PATH);
16503
+ }
15766
16504
  hasEffects(context) {
15767
16505
  if (!this.deoptimized)
15768
16506
  this.applyDeoptimizations();
15769
16507
  return !(context.ignore.returnYield && !this.argument?.hasEffects(context));
15770
16508
  }
16509
+ includeNode(context) {
16510
+ this.included = true;
16511
+ if (!this.deoptimized)
16512
+ this.applyDeoptimizations();
16513
+ this.argument?.includePath(UNKNOWN_PATH, context);
16514
+ }
15771
16515
  render(code, options) {
15772
16516
  if (this.argument) {
15773
16517
  this.argument.render(code, options, { preventASI: true });
@@ -16001,7 +16745,7 @@ const bufferParsers = [
16001
16745
  const annotations = (node.annotations = parseAst_js.convertAnnotations(buffer[position + 1], buffer));
16002
16746
  node.annotationNoSideEffects = annotations.some(comment => comment.type === 'noSideEffects');
16003
16747
  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);
16748
+ scope.addParameterVariables(parameters.map(parameter => parameter.declare('parameter', EMPTY_PATH, UNKNOWN_EXPRESSION)), parameters[parameters.length - 1] instanceof RestElement);
16005
16749
  node.body = convertNode(node, scope.bodyScope, buffer[position + 3], buffer);
16006
16750
  },
16007
16751
  function assignmentExpression(node, position, buffer) {
@@ -16047,7 +16791,7 @@ const bufferParsers = [
16047
16791
  const parameterPosition = buffer[position];
16048
16792
  const parameter = (node.param =
16049
16793
  parameterPosition === 0 ? null : convertNode(node, scope, parameterPosition, buffer));
16050
- parameter?.declare('parameter', UNKNOWN_EXPRESSION);
16794
+ parameter?.declare('parameter', EMPTY_PATH, UNKNOWN_EXPRESSION);
16051
16795
  node.body = convertNode(node, scope.bodyScope, buffer[position + 1], buffer);
16052
16796
  },
16053
16797
  function chainExpression(node, position, buffer) {
@@ -16185,7 +16929,7 @@ const bufferParsers = [
16185
16929
  node.id =
16186
16930
  idPosition === 0 ? null : convertNode(node, scope.parent, idPosition, buffer);
16187
16931
  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);
16932
+ scope.addParameterVariables(parameters.map(parameter => parameter.declare('parameter', EMPTY_PATH, UNKNOWN_EXPRESSION)), parameters[parameters.length - 1] instanceof RestElement);
16189
16933
  node.body = convertNode(node, scope.bodyScope, buffer[position + 4], buffer);
16190
16934
  },
16191
16935
  function functionExpression(node, position, buffer) {
@@ -16198,7 +16942,7 @@ const bufferParsers = [
16198
16942
  const idPosition = buffer[position + 2];
16199
16943
  node.id = idPosition === 0 ? null : convertNode(node, node.idScope, idPosition, buffer);
16200
16944
  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);
16945
+ scope.addParameterVariables(parameters.map(parameter => parameter.declare('parameter', EMPTY_PATH, UNKNOWN_EXPRESSION)), parameters[parameters.length - 1] instanceof RestElement);
16202
16946
  node.body = convertNode(node, scope.bodyScope, buffer[position + 4], buffer);
16203
16947
  },
16204
16948
  function identifier(node, position, buffer) {
@@ -16662,8 +17406,8 @@ class ExportShimVariable extends Variable {
16662
17406
  super(MISSING_EXPORT_SHIM_VARIABLE);
16663
17407
  this.module = module;
16664
17408
  }
16665
- include() {
16666
- super.include();
17409
+ includePath(path, context) {
17410
+ super.includePath(path, context);
16667
17411
  this.module.needsExportShim = true;
16668
17412
  }
16669
17413
  }
@@ -17354,16 +18098,15 @@ class Module {
17354
18098
  markModuleAndImpureDependenciesAsExecuted(this);
17355
18099
  this.graph.needsTreeshakingPass = true;
17356
18100
  }
18101
+ const inclusionContext = createInclusionContext();
17357
18102
  for (const exportName of this.exports.keys()) {
17358
18103
  if (includeNamespaceMembers || exportName !== this.info.syntheticNamedExports) {
17359
18104
  const variable = this.getVariableForExportName(exportName)[0];
17360
18105
  if (!variable) {
17361
18106
  return parseAst_js.error(parseAst_js.logMissingEntryExport(exportName, this.id));
17362
18107
  }
18108
+ this.includeVariable(variable, UNKNOWN_PATH, inclusionContext);
17363
18109
  variable.deoptimizePath(UNKNOWN_PATH);
17364
- if (!variable.included) {
17365
- this.includeVariable(variable);
17366
- }
17367
18110
  }
17368
18111
  }
17369
18112
  for (const name of this.getReexports()) {
@@ -17371,7 +18114,7 @@ class Module {
17371
18114
  if (variable) {
17372
18115
  variable.deoptimizePath(UNKNOWN_PATH);
17373
18116
  if (!variable.included) {
17374
- this.includeVariable(variable);
18117
+ this.includeVariable(variable, UNKNOWN_PATH, inclusionContext);
17375
18118
  }
17376
18119
  if (variable instanceof ExternalVariable) {
17377
18120
  variable.module.reexported = true;
@@ -17392,13 +18135,12 @@ class Module {
17392
18135
  this.graph.needsTreeshakingPass = true;
17393
18136
  }
17394
18137
  let includeNamespaceMembers = false;
18138
+ const inclusionContext = createInclusionContext();
17395
18139
  for (const name of names) {
17396
18140
  const variable = this.getVariableForExportName(name)[0];
17397
18141
  if (variable) {
17398
18142
  variable.deoptimizePath(UNKNOWN_PATH);
17399
- if (!variable.included) {
17400
- this.includeVariable(variable);
17401
- }
18143
+ this.includeVariable(variable, UNKNOWN_PATH, inclusionContext);
17402
18144
  }
17403
18145
  if (!this.exports.has(name) && !this.reexportDescriptions.has(name)) {
17404
18146
  includeNamespaceMembers = true;
@@ -17499,6 +18241,7 @@ class Module {
17499
18241
  manualPureFunctions: this.graph.pureFunctions,
17500
18242
  module: this,
17501
18243
  moduleContext: this.context,
18244
+ newlyIncludedVariableInits: this.graph.newlyIncludedVariableInits,
17502
18245
  options: this.options,
17503
18246
  requestTreeshakingPass: () => (this.graph.needsTreeshakingPass = true),
17504
18247
  traceExport: (name) => this.getVariableForExportName(name)[0],
@@ -17839,13 +18582,13 @@ class Module {
17839
18582
  for (const module of [this, ...this.exportAllModules]) {
17840
18583
  if (module instanceof ExternalModule) {
17841
18584
  const [externalVariable] = module.getVariableForExportName('*');
17842
- externalVariable.include();
18585
+ externalVariable.includePath(UNKNOWN_PATH, createInclusionContext());
17843
18586
  this.includedImports.add(externalVariable);
17844
18587
  externalNamespaces.add(externalVariable);
17845
18588
  }
17846
18589
  else if (module.info.syntheticNamedExports) {
17847
18590
  const syntheticNamespace = module.getSyntheticNamespace();
17848
- syntheticNamespace.include();
18591
+ syntheticNamespace.includePath(UNKNOWN_PATH, createInclusionContext());
17849
18592
  this.includedImports.add(syntheticNamespace);
17850
18593
  syntheticNamespaces.add(syntheticNamespace);
17851
18594
  }
@@ -17855,7 +18598,9 @@ class Module {
17855
18598
  includeDynamicImport(node) {
17856
18599
  const resolution = this.dynamicImports.find(dynamicImport => dynamicImport.node === node).resolution;
17857
18600
  if (resolution instanceof Module) {
17858
- resolution.includedDynamicImporters.push(this);
18601
+ if (!resolution.includedDynamicImporters.includes(this)) {
18602
+ resolution.includedDynamicImporters.push(this);
18603
+ }
17859
18604
  const importedNames = this.options.treeshake
17860
18605
  ? node.getDeterministicImportedNames()
17861
18606
  : undefined;
@@ -17867,15 +18612,15 @@ class Module {
17867
18612
  }
17868
18613
  }
17869
18614
  }
17870
- includeVariable(variable) {
17871
- const variableModule = variable.module;
17872
- if (variable.included) {
18615
+ includeVariable(variable, path, context) {
18616
+ const { included, module: variableModule } = variable;
18617
+ variable.includePath(path, context);
18618
+ if (included) {
17873
18619
  if (variableModule instanceof Module && variableModule !== this) {
17874
18620
  getAndExtendSideEffectModules(variable, this);
17875
18621
  }
17876
18622
  }
17877
18623
  else {
17878
- variable.include();
17879
18624
  this.graph.needsTreeshakingPass = true;
17880
18625
  if (variableModule instanceof Module) {
17881
18626
  if (!variableModule.isExecuted) {
@@ -17892,8 +18637,8 @@ class Module {
17892
18637
  }
17893
18638
  }
17894
18639
  }
17895
- includeVariableInModule(variable) {
17896
- this.includeVariable(variable);
18640
+ includeVariableInModule(variable, path, context) {
18641
+ this.includeVariable(variable, path, context);
17897
18642
  const variableModule = variable.module;
17898
18643
  if (variableModule && variableModule !== this) {
17899
18644
  this.includedImports.add(variable);
@@ -21396,10 +22141,11 @@ class Graph {
21396
22141
  this.options = options;
21397
22142
  this.astLru = flru(5);
21398
22143
  this.cachedModules = new Map();
21399
- this.deoptimizationTracker = new PathTracker();
22144
+ this.deoptimizationTracker = new EntityPathTracker();
21400
22145
  this.entryModules = [];
21401
22146
  this.modulesById = new Map();
21402
22147
  this.needsTreeshakingPass = false;
22148
+ this.newlyIncludedVariableInits = new Set();
21403
22149
  this.phase = BuildPhase.LOAD_AND_PARSE;
21404
22150
  this.scope = new GlobalScope();
21405
22151
  this.watchFiles = Object.create(null);
@@ -21493,6 +22239,7 @@ class Graph {
21493
22239
  }
21494
22240
  if (this.options.treeshake) {
21495
22241
  let treeshakingPass = 1;
22242
+ this.newlyIncludedVariableInits.clear();
21496
22243
  do {
21497
22244
  timeStart(`treeshaking pass ${treeshakingPass}`, 3);
21498
22245
  this.needsTreeshakingPass = false;
@@ -21517,6 +22264,10 @@ class Graph {
21517
22264
  }
21518
22265
  }
21519
22266
  }
22267
+ for (const entity of this.newlyIncludedVariableInits) {
22268
+ this.newlyIncludedVariableInits.delete(entity);
22269
+ entity.include(createInclusionContext(), false);
22270
+ }
21520
22271
  timeEnd(`treeshaking pass ${treeshakingPass++}`, 3);
21521
22272
  } while (this.needsTreeshakingPass);
21522
22273
  }