@rollup/wasm-node 4.30.1 → 4.31.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.30.1
4
- Tue, 07 Jan 2025 10:35:22 GMT - commit 94917087deb9103fbf605c68670ceb3e71a67bf7
3
+ Rollup.js v4.31.0-0
4
+ Tue, 14 Jan 2025 05:57:11 GMT - commit 8c80d5f657f0777d14bd75d446fee3fa4b7639fc
5
5
 
6
6
  https://github.com/rollup/rollup
7
7
 
@@ -17,7 +17,7 @@ const native_js = require('../native.js');
17
17
  const node_perf_hooks = require('node:perf_hooks');
18
18
  const promises = require('node:fs/promises');
19
19
 
20
- var version = "4.30.1";
20
+ var version = "4.31.0-0";
21
21
 
22
22
  function ensureArray$1(items) {
23
23
  if (Array.isArray(items)) {
@@ -3491,71 +3491,6 @@ function renderSystemExportSequenceBeforeExpression(exportedVariable, expression
3491
3491
  }
3492
3492
  }
3493
3493
 
3494
- /** @import { Node } from 'estree' */
3495
-
3496
- /**
3497
- * @param {Node} node
3498
- * @param {Node} parent
3499
- * @returns {boolean}
3500
- */
3501
- function is_reference(node, parent) {
3502
- if (node.type === 'MemberExpression') {
3503
- return !node.computed && is_reference(node.object, node);
3504
- }
3505
-
3506
- if (node.type !== 'Identifier') return false;
3507
-
3508
- switch (parent?.type) {
3509
- // disregard `bar` in `foo.bar`
3510
- case 'MemberExpression':
3511
- return parent.computed || node === parent.object;
3512
-
3513
- // disregard the `foo` in `class {foo(){}}` but keep it in `class {[foo](){}}`
3514
- case 'MethodDefinition':
3515
- return parent.computed;
3516
-
3517
- // disregard the `meta` in `import.meta`
3518
- case 'MetaProperty':
3519
- return parent.meta === node;
3520
-
3521
- // disregard the `foo` in `class {foo=bar}` but keep it in `class {[foo]=bar}` and `class {bar=foo}`
3522
- case 'PropertyDefinition':
3523
- return parent.computed || node === parent.value;
3524
-
3525
- // disregard the `bar` in `{ bar: foo }`, but keep it in `{ [bar]: foo }`
3526
- case 'Property':
3527
- return parent.computed || node === parent.value;
3528
-
3529
- // disregard the `bar` in `export { foo as bar }` or
3530
- // the foo in `import { foo as bar }`
3531
- case 'ExportSpecifier':
3532
- case 'ImportSpecifier':
3533
- return node === parent.local;
3534
-
3535
- // disregard the `foo` in `foo: while (...) { ... break foo; ... continue foo;}`
3536
- case 'LabeledStatement':
3537
- case 'BreakStatement':
3538
- case 'ContinueStatement':
3539
- return false;
3540
-
3541
- default:
3542
- return true;
3543
- }
3544
- }
3545
-
3546
- const PureFunctionKey = Symbol('PureFunction');
3547
- const getPureFunctions = ({ treeshake }) => {
3548
- const pureFunctions = Object.create(null);
3549
- for (const functionName of treeshake ? treeshake.manualPureFunctions : []) {
3550
- let currentFunctions = pureFunctions;
3551
- for (const pathSegment of functionName.split('.')) {
3552
- currentFunctions = currentFunctions[pathSegment] ||= Object.create(null);
3553
- }
3554
- currentFunctions[PureFunctionKey] = true;
3555
- }
3556
- return pureFunctions;
3557
- };
3558
-
3559
3494
  const UnknownKey = Symbol('Unknown Key');
3560
3495
  const UnknownNonAccessorKey = Symbol('Unknown Non-Accessor Key');
3561
3496
  const UnknownInteger = Symbol('Unknown Integer');
@@ -3570,7 +3505,7 @@ const UNKNOWN_PATH = [UnknownKey];
3570
3505
  const UNKNOWN_NON_ACCESSOR_PATH = [UnknownNonAccessorKey];
3571
3506
  const UNKNOWN_INTEGER_PATH = [UnknownInteger];
3572
3507
  const EntitiesKey = Symbol('Entities');
3573
- class PathTracker {
3508
+ class EntityPathTracker {
3574
3509
  constructor() {
3575
3510
  this.entityPaths = Object.create(null, {
3576
3511
  [EntitiesKey]: { value: new Set() }
@@ -3595,14 +3530,14 @@ class PathTracker {
3595
3530
  getEntities(path) {
3596
3531
  let currentPaths = this.entityPaths;
3597
3532
  for (const pathSegment of path) {
3598
- currentPaths = currentPaths[pathSegment] =
3599
- currentPaths[pathSegment] ||
3600
- Object.create(null, { [EntitiesKey]: { value: new Set() } });
3533
+ currentPaths = currentPaths[pathSegment] ||= Object.create(null, {
3534
+ [EntitiesKey]: { value: new Set() }
3535
+ });
3601
3536
  }
3602
3537
  return currentPaths[EntitiesKey];
3603
3538
  }
3604
3539
  }
3605
- const SHARED_RECURSION_TRACKER = new PathTracker();
3540
+ const SHARED_RECURSION_TRACKER = new EntityPathTracker();
3606
3541
  class DiscriminatedPathTracker {
3607
3542
  constructor() {
3608
3543
  this.entityPaths = Object.create(null, {
@@ -3612,9 +3547,9 @@ class DiscriminatedPathTracker {
3612
3547
  trackEntityAtPathAndGetIfTracked(path, discriminator, entity) {
3613
3548
  let currentPaths = this.entityPaths;
3614
3549
  for (const pathSegment of path) {
3615
- currentPaths = currentPaths[pathSegment] =
3616
- currentPaths[pathSegment] ||
3617
- Object.create(null, { [EntitiesKey]: { value: new Map() } });
3550
+ currentPaths = currentPaths[pathSegment] ||= Object.create(null, {
3551
+ [EntitiesKey]: { value: new Map() }
3552
+ });
3618
3553
  }
3619
3554
  const trackedEntities = getOrCreate(currentPaths[EntitiesKey], discriminator, (getNewSet));
3620
3555
  if (trackedEntities.has(entity))
@@ -3623,6 +3558,137 @@ class DiscriminatedPathTracker {
3623
3558
  return false;
3624
3559
  }
3625
3560
  }
3561
+ const UNKNOWN_INCLUDED_PATH = Object.freeze({ [UnknownKey]: parseAst_js.EMPTY_OBJECT });
3562
+ class IncludedPathTracker {
3563
+ constructor() {
3564
+ this.includedPaths = null;
3565
+ }
3566
+ includePathAndGetIfIncluded(path) {
3567
+ let included = true;
3568
+ let parent = this;
3569
+ let parentSegment = 'includedPaths';
3570
+ let currentPaths = (this.includedPaths ||=
3571
+ ((included = false), Object.create(null)));
3572
+ for (const pathSegment of path) {
3573
+ // This means from here, all paths are included
3574
+ if (currentPaths[UnknownKey]) {
3575
+ return true;
3576
+ }
3577
+ // Including UnknownKey automatically includes all nested paths.
3578
+ // From above, we know that UnknownKey is not included yet.
3579
+ if (typeof pathSegment === 'symbol') {
3580
+ // Hopefully, this saves some memory over just setting
3581
+ // currentPaths[UnknownKey] = EMPTY_OBJECT
3582
+ parent[parentSegment] = UNKNOWN_INCLUDED_PATH;
3583
+ return false;
3584
+ }
3585
+ parent = currentPaths;
3586
+ parentSegment = pathSegment;
3587
+ currentPaths = currentPaths[pathSegment] ||= ((included = false), Object.create(null));
3588
+ }
3589
+ return included;
3590
+ }
3591
+ includeAllPaths(entity, context, basePath) {
3592
+ const { includedPaths } = this;
3593
+ if (includedPaths) {
3594
+ includeAllPaths(entity, context, basePath, includedPaths);
3595
+ }
3596
+ }
3597
+ }
3598
+ function includeAllPaths(entity, context, basePath, currentPaths) {
3599
+ if (currentPaths[UnknownKey]) {
3600
+ return entity.includePath([...basePath, UnknownKey], context);
3601
+ }
3602
+ const keys = Object.keys(currentPaths);
3603
+ if (keys.length === 0) {
3604
+ return entity.includePath(basePath, context);
3605
+ }
3606
+ for (const key of keys) {
3607
+ includeAllPaths(entity, context, [...basePath, key], currentPaths[key]);
3608
+ }
3609
+ }
3610
+
3611
+ /** @import { Node } from 'estree' */
3612
+
3613
+ /**
3614
+ * @param {Node} node
3615
+ * @param {Node} parent
3616
+ * @returns {boolean}
3617
+ */
3618
+ function is_reference(node, parent) {
3619
+ if (node.type === 'MemberExpression') {
3620
+ return !node.computed && is_reference(node.object, node);
3621
+ }
3622
+
3623
+ if (node.type !== 'Identifier') return false;
3624
+
3625
+ switch (parent?.type) {
3626
+ // disregard `bar` in `foo.bar`
3627
+ case 'MemberExpression':
3628
+ return parent.computed || node === parent.object;
3629
+
3630
+ // disregard the `foo` in `class {foo(){}}` but keep it in `class {[foo](){}}`
3631
+ case 'MethodDefinition':
3632
+ return parent.computed;
3633
+
3634
+ // disregard the `meta` in `import.meta`
3635
+ case 'MetaProperty':
3636
+ return parent.meta === node;
3637
+
3638
+ // disregard the `foo` in `class {foo=bar}` but keep it in `class {[foo]=bar}` and `class {bar=foo}`
3639
+ case 'PropertyDefinition':
3640
+ return parent.computed || node === parent.value;
3641
+
3642
+ // disregard the `bar` in `{ bar: foo }`, but keep it in `{ [bar]: foo }`
3643
+ case 'Property':
3644
+ return parent.computed || node === parent.value;
3645
+
3646
+ // disregard the `bar` in `export { foo as bar }` or
3647
+ // the foo in `import { foo as bar }`
3648
+ case 'ExportSpecifier':
3649
+ case 'ImportSpecifier':
3650
+ return node === parent.local;
3651
+
3652
+ // disregard the `foo` in `foo: while (...) { ... break foo; ... continue foo;}`
3653
+ case 'LabeledStatement':
3654
+ case 'BreakStatement':
3655
+ case 'ContinueStatement':
3656
+ return false;
3657
+
3658
+ default:
3659
+ return true;
3660
+ }
3661
+ }
3662
+
3663
+ function createInclusionContext() {
3664
+ return {
3665
+ brokenFlow: false,
3666
+ hasBreak: false,
3667
+ hasContinue: false,
3668
+ includedCallArguments: new Set(),
3669
+ includedLabels: new Set()
3670
+ };
3671
+ }
3672
+ function createHasEffectsContext() {
3673
+ return {
3674
+ accessed: new EntityPathTracker(),
3675
+ assigned: new EntityPathTracker(),
3676
+ brokenFlow: false,
3677
+ called: new DiscriminatedPathTracker(),
3678
+ hasBreak: false,
3679
+ hasContinue: false,
3680
+ ignore: {
3681
+ breaks: false,
3682
+ continues: false,
3683
+ labels: new Set(),
3684
+ returnYield: false,
3685
+ this: false
3686
+ },
3687
+ includedLabels: new Set(),
3688
+ instantiated: new DiscriminatedPathTracker(),
3689
+ replacedVariableInits: new Map()
3690
+ };
3691
+ }
3626
3692
 
3627
3693
  function isFlagSet(flags, flag) {
3628
3694
  return (flags & flag) !== 0;
@@ -3662,12 +3728,25 @@ class ExpressionEntity {
3662
3728
  hasEffectsOnInteractionAtPath(_path, _interaction, _context) {
3663
3729
  return true;
3664
3730
  }
3665
- include(_context, _includeChildrenRecursively, _options) {
3731
+ include(context, _includeChildrenRecursively, _options) {
3732
+ if (!this.included)
3733
+ this.includeNode(context);
3734
+ }
3735
+ includeNode(_context) {
3666
3736
  this.included = true;
3667
3737
  }
3668
- includeCallArguments(context, parameters) {
3669
- for (const argument of parameters) {
3670
- argument.include(context, false);
3738
+ includePath(_path, context) {
3739
+ if (!this.included)
3740
+ this.includeNode(context);
3741
+ }
3742
+ /* We are both including and including an unknown path here as the former
3743
+ * ensures that nested nodes are included while the latter ensures that all
3744
+ * paths of the expression are included.
3745
+ * */
3746
+ includeCallArguments(context, interaction) {
3747
+ for (const argument of interaction.args) {
3748
+ argument?.includePath(UNKNOWN_PATH, context);
3749
+ argument?.include(context, false);
3671
3750
  }
3672
3751
  }
3673
3752
  shouldBeIncluded(_context) {
@@ -3706,6 +3785,19 @@ const NODE_INTERACTION_UNKNOWN_CALL = {
3706
3785
  withNew: false
3707
3786
  };
3708
3787
 
3788
+ const PureFunctionKey = Symbol('PureFunction');
3789
+ const getPureFunctions = ({ treeshake }) => {
3790
+ const pureFunctions = Object.create(null);
3791
+ for (const functionName of treeshake ? treeshake.manualPureFunctions : []) {
3792
+ let currentFunctions = pureFunctions;
3793
+ for (const pathSegment of functionName.split('.')) {
3794
+ currentFunctions = currentFunctions[pathSegment] ||= Object.create(null);
3795
+ }
3796
+ currentFunctions[PureFunctionKey] = true;
3797
+ }
3798
+ return pureFunctions;
3799
+ };
3800
+
3709
3801
  class Variable extends ExpressionEntity {
3710
3802
  markReassigned() {
3711
3803
  this.isReassigned = true;
@@ -3782,9 +3874,9 @@ class Variable extends ExpressionEntity {
3782
3874
  * has not been included previously. Once a variable is included, it should
3783
3875
  * take care all its declarations are included.
3784
3876
  */
3785
- include() {
3877
+ includePath(path, context) {
3786
3878
  this.included = true;
3787
- this.renderedLikeHoisted?.include();
3879
+ this.renderedLikeHoisted?.includePath(path, context);
3788
3880
  }
3789
3881
  /**
3790
3882
  * Links the rendered name of this variable to another variable and includes
@@ -3816,8 +3908,8 @@ class ExternalVariable extends Variable {
3816
3908
  hasEffectsOnInteractionAtPath(path, { type }) {
3817
3909
  return type !== INTERACTION_ACCESSED || path.length > (this.isNamespace ? 1 : 0);
3818
3910
  }
3819
- include() {
3820
- super.include();
3911
+ includePath(path, context) {
3912
+ super.includePath(path, context);
3821
3913
  this.module.used = true;
3822
3914
  }
3823
3915
  }
@@ -4116,36 +4208,6 @@ const childNodeKeys = {
4116
4208
  YieldExpression: ['argument']
4117
4209
  };
4118
4210
 
4119
- function createInclusionContext() {
4120
- return {
4121
- brokenFlow: false,
4122
- hasBreak: false,
4123
- hasContinue: false,
4124
- includedCallArguments: new Set(),
4125
- includedLabels: new Set()
4126
- };
4127
- }
4128
- function createHasEffectsContext() {
4129
- return {
4130
- accessed: new PathTracker(),
4131
- assigned: new PathTracker(),
4132
- brokenFlow: false,
4133
- called: new DiscriminatedPathTracker(),
4134
- hasBreak: false,
4135
- hasContinue: false,
4136
- ignore: {
4137
- breaks: false,
4138
- continues: false,
4139
- labels: new Set(),
4140
- returnYield: false,
4141
- this: false
4142
- },
4143
- includedLabels: new Set(),
4144
- instantiated: new DiscriminatedPathTracker(),
4145
- replacedVariableInits: new Map()
4146
- };
4147
- }
4148
-
4149
4211
  const INCLUDE_PARAMETERS = 'variables';
4150
4212
  const IS_SKIPPED_CHAIN = Symbol('IS_SKIPPED_CHAIN');
4151
4213
  class NodeBase extends ExpressionEntity {
@@ -4215,9 +4277,8 @@ class NodeBase extends ExpressionEntity {
4215
4277
  this.hasEffectsOnInteractionAtPath(EMPTY_PATH, this.assignmentInteraction, context));
4216
4278
  }
4217
4279
  include(context, includeChildrenRecursively, _options) {
4218
- if (!this.deoptimized)
4219
- this.applyDeoptimizations();
4220
- this.included = true;
4280
+ if (!this.included)
4281
+ this.includeNode(context);
4221
4282
  for (const key of childNodeKeys[this.type]) {
4222
4283
  const value = this[key];
4223
4284
  if (value === null)
@@ -4232,6 +4293,24 @@ class NodeBase extends ExpressionEntity {
4232
4293
  }
4233
4294
  }
4234
4295
  }
4296
+ includeNode(context) {
4297
+ this.included = true;
4298
+ if (!this.deoptimized)
4299
+ this.applyDeoptimizations();
4300
+ for (const key of childNodeKeys[this.type]) {
4301
+ const value = this[key];
4302
+ if (value === null)
4303
+ continue;
4304
+ if (Array.isArray(value)) {
4305
+ for (const child of value) {
4306
+ child?.includePath(UNKNOWN_PATH, context);
4307
+ }
4308
+ }
4309
+ else {
4310
+ value.includePath(UNKNOWN_PATH, context);
4311
+ }
4312
+ }
4313
+ }
4235
4314
  includeAsAssignmentTarget(context, includeChildrenRecursively, _deoptimizeAccess) {
4236
4315
  this.include(context, includeChildrenRecursively);
4237
4316
  }
@@ -4335,6 +4414,17 @@ class NodeBase extends ExpressionEntity {
4335
4414
  function createChildNodeKeysForNode(esTreeNode) {
4336
4415
  return Object.keys(esTreeNode).filter(key => typeof esTreeNode[key] === 'object' && key.charCodeAt(0) !== 95 /* _ */);
4337
4416
  }
4417
+ function onlyIncludeSelf() {
4418
+ this.included = true;
4419
+ if (!this.deoptimized)
4420
+ this.applyDeoptimizations();
4421
+ }
4422
+ function onlyIncludeSelfNoDeoptimize() {
4423
+ this.included = true;
4424
+ }
4425
+ function doNotDeoptimize() {
4426
+ this.deoptimized = true;
4427
+ }
4338
4428
 
4339
4429
  function isObjectExpressionNode(node) {
4340
4430
  return node instanceof NodeBase && node.type === parseAst_js.ObjectExpression;
@@ -4347,8 +4437,8 @@ function assembleMemberDescriptions(memberDescriptions, inheritedDescriptions =
4347
4437
  return Object.create(inheritedDescriptions, memberDescriptions);
4348
4438
  }
4349
4439
  const UNDEFINED_EXPRESSION = new (class UndefinedExpression extends ExpressionEntity {
4350
- getLiteralValueAtPath() {
4351
- return undefined;
4440
+ getLiteralValueAtPath(path) {
4441
+ return path.length > 0 ? UnknownValue : undefined;
4352
4442
  }
4353
4443
  })();
4354
4444
  const returnsUnknown = {
@@ -4545,31 +4635,6 @@ function getMemberReturnExpressionWhenCalled(members, memberName) {
4545
4635
  return [members[memberName].returns, false];
4546
4636
  }
4547
4637
 
4548
- class SpreadElement extends NodeBase {
4549
- deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
4550
- if (path.length > 0) {
4551
- this.argument.deoptimizeArgumentsOnInteractionAtPath(interaction, UNKNOWN_PATH, recursionTracker);
4552
- }
4553
- }
4554
- hasEffects(context) {
4555
- if (!this.deoptimized)
4556
- this.applyDeoptimizations();
4557
- const { propertyReadSideEffects } = this.scope.context.options
4558
- .treeshake;
4559
- return (this.argument.hasEffects(context) ||
4560
- (propertyReadSideEffects &&
4561
- (propertyReadSideEffects === 'always' ||
4562
- this.argument.hasEffectsOnInteractionAtPath(UNKNOWN_PATH, NODE_INTERACTION_UNKNOWN_ACCESS, context))));
4563
- }
4564
- applyDeoptimizations() {
4565
- this.deoptimized = true;
4566
- // Only properties of properties of the argument could become subject to reassignment
4567
- // This will also reassign the return values of iterators
4568
- this.argument.deoptimizePath([UnknownKey, UnknownKey]);
4569
- this.scope.context.requestTreeshakingPass();
4570
- }
4571
- }
4572
-
4573
4638
  class Method extends ExpressionEntity {
4574
4639
  constructor(description) {
4575
4640
  super();
@@ -4695,6 +4760,7 @@ class ObjectEntity extends ExpressionEntity {
4695
4760
  this.unknownIntegerProps = [];
4696
4761
  this.unmatchableGetters = [];
4697
4762
  this.unmatchablePropertiesAndGetters = [];
4763
+ this.unmatchablePropertiesAndSetters = [];
4698
4764
  this.unmatchableSetters = [];
4699
4765
  if (Array.isArray(properties)) {
4700
4766
  this.buildPropertyMaps(properties);
@@ -4851,7 +4917,12 @@ class ObjectEntity extends ExpressionEntity {
4851
4917
  }
4852
4918
  getLiteralValueAtPath(path, recursionTracker, origin) {
4853
4919
  if (path.length === 0) {
4854
- return UnknownTruthyValue;
4920
+ // This should actually be "UnknownTruthyValue". However, this currently
4921
+ // causes an issue with TypeScript enums in files with moduleSideEffects:
4922
+ // false because we cannot properly track whether a "var" has been
4923
+ // initialized. This should be reverted once we can properly track this.
4924
+ // return UnknownTruthyValue;
4925
+ return UnknownValue;
4855
4926
  }
4856
4927
  const key = path[0];
4857
4928
  const expressionAtPath = this.getMemberExpressionAndTrackDeopt(key, origin);
@@ -4929,9 +5000,38 @@ class ObjectEntity extends ExpressionEntity {
4929
5000
  }
4930
5001
  return false;
4931
5002
  }
5003
+ include(context, includeChildrenRecursively) {
5004
+ this.included = true;
5005
+ for (const property of this.allProperties) {
5006
+ if (includeChildrenRecursively || property.shouldBeIncluded(context)) {
5007
+ property.include(context, includeChildrenRecursively);
5008
+ }
5009
+ }
5010
+ this.prototypeExpression?.include(context, includeChildrenRecursively);
5011
+ }
5012
+ includePath(path, context) {
5013
+ this.included = true;
5014
+ if (path.length === 0)
5015
+ return;
5016
+ const [key, ...subPath] = path;
5017
+ const [includedMembers, includedPath] = typeof key === 'string'
5018
+ ? [
5019
+ [
5020
+ ...new Set([
5021
+ ...(this.propertiesAndGettersByKey[key] || this.unmatchablePropertiesAndGetters),
5022
+ ...(this.propertiesAndSettersByKey[key] || this.unmatchablePropertiesAndSetters)
5023
+ ])
5024
+ ],
5025
+ subPath
5026
+ ]
5027
+ : [this.allProperties, UNKNOWN_PATH];
5028
+ for (const property of includedMembers) {
5029
+ property.includePath(includedPath, context);
5030
+ }
5031
+ this.prototypeExpression?.includePath(path, context);
5032
+ }
4932
5033
  buildPropertyMaps(properties) {
4933
- const { allProperties, propertiesAndGettersByKey, propertiesAndSettersByKey, settersByKey, gettersByKey, unknownIntegerProps, unmatchablePropertiesAndGetters, unmatchableGetters, unmatchableSetters } = this;
4934
- const unmatchablePropertiesAndSetters = [];
5034
+ const { allProperties, propertiesAndGettersByKey, propertiesAndSettersByKey, settersByKey, gettersByKey, unknownIntegerProps, unmatchablePropertiesAndGetters, unmatchablePropertiesAndSetters, unmatchableGetters, unmatchableSetters } = this;
4935
5035
  for (let index = properties.length - 1; index >= 0; index--) {
4936
5036
  const { key, kind, property } = properties[index];
4937
5037
  allProperties.push(property);
@@ -5201,6 +5301,37 @@ const ARRAY_PROTOTYPE = new ObjectEntity({
5201
5301
  values: METHOD_DEOPTS_SELF_RETURNS_UNKNOWN
5202
5302
  }, OBJECT_PROTOTYPE, true);
5203
5303
 
5304
+ class SpreadElement extends NodeBase {
5305
+ deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
5306
+ if (path.length > 0) {
5307
+ this.argument.deoptimizeArgumentsOnInteractionAtPath(interaction, UNKNOWN_PATH, recursionTracker);
5308
+ }
5309
+ }
5310
+ hasEffects(context) {
5311
+ if (!this.deoptimized)
5312
+ this.applyDeoptimizations();
5313
+ const { propertyReadSideEffects } = this.scope.context.options
5314
+ .treeshake;
5315
+ return (this.argument.hasEffects(context) ||
5316
+ (propertyReadSideEffects &&
5317
+ (propertyReadSideEffects === 'always' ||
5318
+ this.argument.hasEffectsOnInteractionAtPath(UNKNOWN_PATH, NODE_INTERACTION_UNKNOWN_ACCESS, context))));
5319
+ }
5320
+ includeNode(context) {
5321
+ this.included = true;
5322
+ if (!this.deoptimized)
5323
+ this.applyDeoptimizations();
5324
+ this.argument.includePath(UNKNOWN_PATH, context);
5325
+ }
5326
+ applyDeoptimizations() {
5327
+ this.deoptimized = true;
5328
+ // Only properties of properties of the argument could become subject to reassignment
5329
+ // This will also reassign the return values of iterators
5330
+ this.argument.deoptimizePath([UnknownKey, UnknownKey]);
5331
+ this.scope.context.requestTreeshakingPass();
5332
+ }
5333
+ }
5334
+
5204
5335
  class ArrayExpression extends NodeBase {
5205
5336
  constructor() {
5206
5337
  super(...arguments);
@@ -5221,6 +5352,16 @@ class ArrayExpression extends NodeBase {
5221
5352
  hasEffectsOnInteractionAtPath(path, interaction, context) {
5222
5353
  return this.getObjectEntity().hasEffectsOnInteractionAtPath(path, interaction, context);
5223
5354
  }
5355
+ includeNode(context) {
5356
+ this.included = true;
5357
+ if (!this.deoptimized)
5358
+ this.applyDeoptimizations();
5359
+ for (const element of this.elements) {
5360
+ if (element) {
5361
+ element?.includePath(UNKNOWN_PATH, context);
5362
+ }
5363
+ }
5364
+ }
5224
5365
  applyDeoptimizations() {
5225
5366
  this.deoptimized = true;
5226
5367
  let hasSpread = false;
@@ -6288,17 +6429,37 @@ class GlobalVariable extends Variable {
6288
6429
  }
6289
6430
  }
6290
6431
 
6432
+ // To avoid infinite recursions
6433
+ const MAX_PATH_DEPTH = 6;
6434
+ // If a path is longer than MAX_PATH_DEPTH, it is truncated so that it is at
6435
+ // most MAX_PATH_DEPTH long. The last element is always UnknownKey
6436
+ const limitConcatenatedPathDepth = (path1, path2) => {
6437
+ const { length: length1 } = path1;
6438
+ const { length: length2 } = path2;
6439
+ return length1 === 0
6440
+ ? path2
6441
+ : length2 === 0
6442
+ ? path1
6443
+ : length1 + length2 > MAX_PATH_DEPTH
6444
+ ? [...path1, ...path2.slice(0, MAX_PATH_DEPTH - 1 - path1.length), 'UnknownKey']
6445
+ : [...path1, ...path2];
6446
+ };
6447
+
6291
6448
  class LocalVariable extends Variable {
6292
- constructor(name, declarator, init, context, kind) {
6449
+ constructor(name, declarator, init,
6450
+ /** if this is non-empty, the actual init is this path of this.init */
6451
+ initPath, context, kind) {
6293
6452
  super(name);
6294
6453
  this.init = init;
6454
+ this.initPath = initPath;
6455
+ this.kind = kind;
6295
6456
  this.calledFromTryStatement = false;
6296
6457
  this.additionalInitializers = null;
6458
+ this.includedPathTracker = new IncludedPathTracker();
6297
6459
  this.expressionsToBeDeoptimized = [];
6298
6460
  this.declarations = declarator ? [declarator] : [];
6299
6461
  this.deoptimizationTracker = context.deoptimizationTracker;
6300
6462
  this.module = context.module;
6301
- this.kind = kind;
6302
6463
  }
6303
6464
  addDeclaration(identifier, init) {
6304
6465
  this.declarations.push(identifier);
@@ -6309,15 +6470,16 @@ class LocalVariable extends Variable {
6309
6470
  for (const initializer of this.additionalInitializers) {
6310
6471
  initializer.deoptimizePath(UNKNOWN_PATH);
6311
6472
  }
6312
- this.additionalInitializers = null;
6313
6473
  }
6314
6474
  }
6315
6475
  deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
6316
- if (this.isReassigned) {
6476
+ if (this.isReassigned || path.length + this.initPath.length > MAX_PATH_DEPTH) {
6317
6477
  deoptimizeInteraction(interaction);
6318
6478
  return;
6319
6479
  }
6320
- recursionTracker.withTrackedEntityAtPath(path, this.init, () => this.init.deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker), undefined);
6480
+ recursionTracker.withTrackedEntityAtPath(path, this.init, () => {
6481
+ this.init.deoptimizeArgumentsOnInteractionAtPath(interaction, [...this.initPath, ...path], recursionTracker);
6482
+ }, undefined);
6321
6483
  }
6322
6484
  deoptimizePath(path) {
6323
6485
  if (this.isReassigned ||
@@ -6331,37 +6493,40 @@ class LocalVariable extends Variable {
6331
6493
  for (const expression of expressionsToBeDeoptimized) {
6332
6494
  expression.deoptimizeCache();
6333
6495
  }
6334
- this.init.deoptimizePath(UNKNOWN_PATH);
6496
+ this.init.deoptimizePath([...this.initPath, UnknownKey]);
6335
6497
  }
6336
6498
  else {
6337
- this.init.deoptimizePath(path);
6499
+ this.init.deoptimizePath(limitConcatenatedPathDepth(this.initPath, path));
6338
6500
  }
6339
6501
  }
6340
6502
  getLiteralValueAtPath(path, recursionTracker, origin) {
6341
- if (this.isReassigned) {
6503
+ if (this.isReassigned || path.length + this.initPath.length > MAX_PATH_DEPTH) {
6342
6504
  return UnknownValue;
6343
6505
  }
6344
6506
  return recursionTracker.withTrackedEntityAtPath(path, this.init, () => {
6345
6507
  this.expressionsToBeDeoptimized.push(origin);
6346
- return this.init.getLiteralValueAtPath(path, recursionTracker, origin);
6508
+ return this.init.getLiteralValueAtPath([...this.initPath, ...path], recursionTracker, origin);
6347
6509
  }, UnknownValue);
6348
6510
  }
6349
6511
  getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin) {
6350
- if (this.isReassigned) {
6512
+ if (this.isReassigned || path.length + this.initPath.length > MAX_PATH_DEPTH) {
6351
6513
  return UNKNOWN_RETURN_EXPRESSION;
6352
6514
  }
6353
6515
  return recursionTracker.withTrackedEntityAtPath(path, this.init, () => {
6354
6516
  this.expressionsToBeDeoptimized.push(origin);
6355
- return this.init.getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin);
6517
+ return this.init.getReturnExpressionWhenCalledAtPath([...this.initPath, ...path], interaction, recursionTracker, origin);
6356
6518
  }, UNKNOWN_RETURN_EXPRESSION);
6357
6519
  }
6358
6520
  hasEffectsOnInteractionAtPath(path, interaction, context) {
6521
+ if (path.length + this.initPath.length > MAX_PATH_DEPTH) {
6522
+ return true;
6523
+ }
6359
6524
  switch (interaction.type) {
6360
6525
  case INTERACTION_ACCESSED: {
6361
6526
  if (this.isReassigned)
6362
6527
  return true;
6363
6528
  return (!context.accessed.trackEntityAtPathAndGetIfTracked(path, this) &&
6364
- this.init.hasEffectsOnInteractionAtPath(path, interaction, context));
6529
+ this.init.hasEffectsOnInteractionAtPath([...this.initPath, ...path], interaction, context));
6365
6530
  }
6366
6531
  case INTERACTION_ASSIGNED: {
6367
6532
  if (this.included)
@@ -6371,44 +6536,63 @@ class LocalVariable extends Variable {
6371
6536
  if (this.isReassigned)
6372
6537
  return true;
6373
6538
  return (!context.assigned.trackEntityAtPathAndGetIfTracked(path, this) &&
6374
- this.init.hasEffectsOnInteractionAtPath(path, interaction, context));
6539
+ this.init.hasEffectsOnInteractionAtPath([...this.initPath, ...path], interaction, context));
6375
6540
  }
6376
6541
  case INTERACTION_CALLED: {
6377
6542
  if (this.isReassigned)
6378
6543
  return true;
6379
6544
  return (!(interaction.withNew ? context.instantiated : context.called).trackEntityAtPathAndGetIfTracked(path, interaction.args, this) &&
6380
- this.init.hasEffectsOnInteractionAtPath(path, interaction, context));
6545
+ this.init.hasEffectsOnInteractionAtPath([...this.initPath, ...path], interaction, context));
6381
6546
  }
6382
6547
  }
6383
6548
  }
6384
- include() {
6385
- if (!this.included) {
6386
- super.include();
6549
+ includePath(path, context) {
6550
+ if (!this.includedPathTracker.includePathAndGetIfIncluded(path)) {
6551
+ this.module.scope.context.requestTreeshakingPass();
6552
+ if (!this.included) {
6553
+ // This will reduce the number of tree-shaking passes by eagerly
6554
+ // including inits. By pushing this here instead of directly including
6555
+ // we avoid deep call stacks.
6556
+ this.module.scope.context.newlyIncludedVariableInits.add(this.init);
6557
+ }
6558
+ super.includePath(path, context);
6387
6559
  for (const declaration of this.declarations) {
6388
6560
  // If node is a default export, it can save a tree-shaking run to include the full declaration now
6389
6561
  if (!declaration.included)
6390
- declaration.include(createInclusionContext(), false);
6562
+ declaration.include(context, false);
6391
6563
  let node = declaration.parent;
6392
6564
  while (!node.included) {
6393
6565
  // We do not want to properly include parents in case they are part of a dead branch
6394
6566
  // in which case .include() might pull in more dead code
6395
- node.included = true;
6567
+ node.includeNode(context);
6396
6568
  if (node.type === parseAst_js.Program)
6397
6569
  break;
6398
6570
  node = node.parent;
6399
6571
  }
6400
6572
  }
6573
+ // We need to make sure we include the correct path of the init
6574
+ if (path.length > 0) {
6575
+ this.init.includePath(limitConcatenatedPathDepth(this.initPath, path), context);
6576
+ this.additionalInitializers?.forEach(initializer => initializer.includePath(UNKNOWN_PATH, context));
6577
+ }
6401
6578
  }
6402
6579
  }
6403
- includeCallArguments(context, parameters) {
6404
- if (this.isReassigned || context.includedCallArguments.has(this.init)) {
6405
- for (const argument of parameters) {
6406
- argument.include(context, false);
6580
+ includeCallArguments(context, interaction) {
6581
+ if (this.isReassigned ||
6582
+ context.includedCallArguments.has(this.init) ||
6583
+ // This can be removed again once we can include arguments when called at
6584
+ // a specific path
6585
+ this.initPath.length > 0) {
6586
+ for (const argument of interaction.args) {
6587
+ if (argument) {
6588
+ argument.includePath(UNKNOWN_PATH, context);
6589
+ argument.include(context, false);
6590
+ }
6407
6591
  }
6408
6592
  }
6409
6593
  else {
6410
6594
  context.includedCallArguments.add(this.init);
6411
- this.init.includeCallArguments(context, parameters);
6595
+ this.init.includeCallArguments(context, interaction);
6412
6596
  context.includedCallArguments.delete(this.init);
6413
6597
  }
6414
6598
  }
@@ -6488,18 +6672,31 @@ class IdentifierBase extends NodeBase {
6488
6672
  }
6489
6673
  }
6490
6674
  }
6491
- include() {
6675
+ include(context) {
6676
+ if (!this.included)
6677
+ this.includeNode(context);
6678
+ }
6679
+ includeNode(context) {
6680
+ this.included = true;
6492
6681
  if (!this.deoptimized)
6493
6682
  this.applyDeoptimizations();
6683
+ if (this.variable !== null) {
6684
+ this.scope.context.includeVariableInModule(this.variable, EMPTY_PATH, context);
6685
+ }
6686
+ }
6687
+ includePath(path, context) {
6494
6688
  if (!this.included) {
6495
6689
  this.included = true;
6496
6690
  if (this.variable !== null) {
6497
- this.scope.context.includeVariableInModule(this.variable);
6691
+ this.scope.context.includeVariableInModule(this.variable, path, context);
6498
6692
  }
6499
6693
  }
6694
+ else if (path.length > 0) {
6695
+ this.variable?.includePath(path, context);
6696
+ }
6500
6697
  }
6501
- includeCallArguments(context, parameters) {
6502
- this.variable.includeCallArguments(context, parameters);
6698
+ includeCallArguments(context, interaction) {
6699
+ this.variable.includeCallArguments(context, interaction);
6503
6700
  }
6504
6701
  isPossibleTDZ() {
6505
6702
  // return cached value to avoid issues with the next tree-shaking pass
@@ -6582,11 +6779,40 @@ function closestParentFunctionOrProgram(node) {
6582
6779
  return node;
6583
6780
  }
6584
6781
 
6782
+ class ObjectMember extends ExpressionEntity {
6783
+ constructor(object, path) {
6784
+ super();
6785
+ this.object = object;
6786
+ this.path = path;
6787
+ }
6788
+ deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
6789
+ this.object.deoptimizeArgumentsOnInteractionAtPath(interaction, [...this.path, ...path], recursionTracker);
6790
+ }
6791
+ deoptimizePath(path) {
6792
+ this.object.deoptimizePath([...this.path, ...path]);
6793
+ }
6794
+ getLiteralValueAtPath(path, recursionTracker, origin) {
6795
+ return this.object.getLiteralValueAtPath([...this.path, ...path], recursionTracker, origin);
6796
+ }
6797
+ getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin) {
6798
+ return this.object.getReturnExpressionWhenCalledAtPath([...this.path, ...path], interaction, recursionTracker, origin);
6799
+ }
6800
+ hasEffectsOnInteractionAtPath(path, interaction, context) {
6801
+ return this.object.hasEffectsOnInteractionAtPath([...this.path, ...path], interaction, context);
6802
+ }
6803
+ }
6804
+
6585
6805
  class Identifier extends IdentifierBase {
6586
6806
  constructor() {
6587
6807
  super(...arguments);
6588
6808
  this.variable = null;
6589
6809
  }
6810
+ get isDestructuringDeoptimized() {
6811
+ return isFlagSet(this.flags, 16777216 /* Flag.destructuringDeoptimized */);
6812
+ }
6813
+ set isDestructuringDeoptimized(value) {
6814
+ this.flags = setFlag(this.flags, 16777216 /* Flag.destructuringDeoptimized */, value);
6815
+ }
6590
6816
  addExportedVariables(variables, exportNamesByVariable) {
6591
6817
  if (exportNamesByVariable.has(this.variable)) {
6592
6818
  variables.push(this.variable);
@@ -6599,42 +6825,52 @@ class Identifier extends IdentifierBase {
6599
6825
  this.isVariableReference = true;
6600
6826
  }
6601
6827
  }
6602
- declare(kind, init) {
6603
- let variable;
6604
- const { treeshake } = this.scope.context.options;
6605
- switch (kind) {
6606
- case 'var': {
6607
- variable = this.scope.addDeclaration(this, this.scope.context, init, kind);
6608
- if (treeshake && treeshake.correctVarValueBeforeDeclaration) {
6609
- // Necessary to make sure the init is deoptimized. We cannot call deoptimizePath here.
6610
- variable.markInitializersForDeoptimization();
6611
- }
6612
- break;
6613
- }
6614
- case 'function': {
6615
- // in strict mode, functions are only hoisted within a scope but not across block scopes
6616
- variable = this.scope.addDeclaration(this, this.scope.context, init, kind);
6617
- break;
6618
- }
6619
- case 'let':
6620
- case 'const':
6621
- case 'using':
6622
- case 'await using':
6623
- case 'class': {
6624
- variable = this.scope.addDeclaration(this, this.scope.context, init, kind);
6625
- break;
6626
- }
6627
- case 'parameter': {
6628
- variable = this.scope.addParameterDeclaration(this);
6629
- break;
6630
- }
6631
- /* istanbul ignore next */
6632
- default: {
6633
- /* istanbul ignore next */
6634
- throw new Error(`Internal Error: Unexpected identifier kind ${kind}.`);
6828
+ declare(kind, destructuredInitPath, init) {
6829
+ let variable;
6830
+ const { treeshake } = this.scope.context.options;
6831
+ if (kind === 'parameter') {
6832
+ variable = this.scope.addParameterDeclaration(this, destructuredInitPath);
6833
+ }
6834
+ else {
6835
+ variable = this.scope.addDeclaration(this, this.scope.context, init, destructuredInitPath, kind);
6836
+ if (kind === 'var' && treeshake && treeshake.correctVarValueBeforeDeclaration) {
6837
+ // Necessary to make sure the init is deoptimized. We cannot call deoptimizePath here.
6838
+ variable.markInitializersForDeoptimization();
6839
+ }
6840
+ }
6841
+ return [(this.variable = variable)];
6842
+ }
6843
+ deoptimizeAssignment(destructuredInitPath, init) {
6844
+ this.deoptimizePath(EMPTY_PATH);
6845
+ init.deoptimizePath([...destructuredInitPath, UnknownKey]);
6846
+ }
6847
+ hasEffectsWhenDestructuring(context, destructuredInitPath, init) {
6848
+ return (destructuredInitPath.length > 0 &&
6849
+ init.hasEffectsOnInteractionAtPath(destructuredInitPath, NODE_INTERACTION_UNKNOWN_ACCESS, context));
6850
+ }
6851
+ includeDestructuredIfNecessary(context, destructuredInitPath, init) {
6852
+ if (destructuredInitPath.length > 0 && !this.isDestructuringDeoptimized) {
6853
+ this.isDestructuringDeoptimized = true;
6854
+ init.deoptimizeArgumentsOnInteractionAtPath({
6855
+ args: [new ObjectMember(init, destructuredInitPath.slice(0, -1))],
6856
+ type: INTERACTION_ACCESSED
6857
+ }, destructuredInitPath, SHARED_RECURSION_TRACKER);
6858
+ }
6859
+ const { propertyReadSideEffects } = this.scope.context.options
6860
+ .treeshake;
6861
+ if ((this.included ||=
6862
+ destructuredInitPath.length > 0 &&
6863
+ !context.brokenFlow &&
6864
+ propertyReadSideEffects &&
6865
+ (propertyReadSideEffects === 'always' ||
6866
+ init.hasEffectsOnInteractionAtPath(destructuredInitPath, NODE_INTERACTION_UNKNOWN_ACCESS, createHasEffectsContext())))) {
6867
+ if (this.variable && !this.variable.included) {
6868
+ this.scope.context.includeVariableInModule(this.variable, EMPTY_PATH, context);
6635
6869
  }
6870
+ init.includePath(destructuredInitPath, context);
6871
+ return true;
6636
6872
  }
6637
- return [(this.variable = variable)];
6873
+ return false;
6638
6874
  }
6639
6875
  markDeclarationReached() {
6640
6876
  this.variable.initReached = true;
@@ -6688,18 +6924,17 @@ class Scope {
6688
6924
  - then the variable is still declared in the hoisted outer scope, but the initializer is assigned to the parameter
6689
6925
  - const, let, class, and function except in the cases above cannot redeclare anything
6690
6926
  */
6691
- addDeclaration(identifier, context, init, kind) {
6927
+ addDeclaration(identifier, context, init, destructuredInitPath, kind) {
6692
6928
  const name = identifier.name;
6693
6929
  const existingVariable = this.hoistedVariables?.get(name) || this.variables.get(name);
6694
6930
  if (existingVariable) {
6695
- const existingKind = existingVariable.kind;
6696
- if (kind === 'var' && existingKind === 'var') {
6931
+ if (kind === 'var' && existingVariable.kind === 'var') {
6697
6932
  existingVariable.addDeclaration(identifier, init);
6698
6933
  return existingVariable;
6699
6934
  }
6700
6935
  context.error(parseAst_js.logRedeclarationError(name), identifier.start);
6701
6936
  }
6702
- const newVariable = new LocalVariable(identifier.name, identifier, init, context, kind);
6937
+ const newVariable = new LocalVariable(identifier.name, identifier, init, destructuredInitPath, context, kind);
6703
6938
  this.variables.set(name, newVariable);
6704
6939
  return newVariable;
6705
6940
  }
@@ -6875,7 +7110,6 @@ class MethodBase extends NodeBase {
6875
7110
  }
6876
7111
  return this.getAccessedValue()[0].hasEffectsOnInteractionAtPath(path, interaction, context);
6877
7112
  }
6878
- applyDeoptimizations() { }
6879
7113
  getAccessedValue() {
6880
7114
  if (this.accessedValue === null) {
6881
7115
  if (this.kind === 'get') {
@@ -6889,19 +7123,20 @@ class MethodBase extends NodeBase {
6889
7123
  return this.accessedValue;
6890
7124
  }
6891
7125
  }
7126
+ MethodBase.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
7127
+ MethodBase.prototype.applyDeoptimizations = doNotDeoptimize;
6892
7128
 
6893
7129
  class MethodDefinition extends MethodBase {
6894
7130
  hasEffects(context) {
6895
7131
  return super.hasEffects(context) || checkEffectForNodes(this.decorators, context);
6896
7132
  }
6897
- applyDeoptimizations() { }
6898
7133
  }
6899
7134
 
6900
7135
  class BlockScope extends ChildScope {
6901
7136
  constructor(parent) {
6902
7137
  super(parent, parent.context);
6903
7138
  }
6904
- addDeclaration(identifier, context, init, kind) {
7139
+ addDeclaration(identifier, context, init, destructuredInitPath, kind) {
6905
7140
  if (kind === 'var') {
6906
7141
  const name = identifier.name;
6907
7142
  const existingVariable = this.hoistedVariables?.get(name) || this.variables.get(name);
@@ -6913,7 +7148,7 @@ class BlockScope extends ChildScope {
6913
7148
  }
6914
7149
  return context.error(parseAst_js.logRedeclarationError(name), identifier.start);
6915
7150
  }
6916
- const declaredVariable = this.parent.addDeclaration(identifier, context, init, kind);
7151
+ const declaredVariable = this.parent.addDeclaration(identifier, context, init, destructuredInitPath, kind);
6917
7152
  // Necessary to make sure the init is deoptimized for conditional declarations.
6918
7153
  // We cannot call deoptimizePath here.
6919
7154
  declaredVariable.markInitializersForDeoptimization();
@@ -6921,7 +7156,7 @@ class BlockScope extends ChildScope {
6921
7156
  this.addHoistedVariable(name, declaredVariable);
6922
7157
  return declaredVariable;
6923
7158
  }
6924
- return super.addDeclaration(identifier, context, init, kind);
7159
+ return super.addDeclaration(identifier, context, init, destructuredInitPath, kind);
6925
7160
  }
6926
7161
  }
6927
7162
 
@@ -6953,33 +7188,12 @@ class StaticBlock extends NodeBase {
6953
7188
  }
6954
7189
  }
6955
7190
  }
7191
+ StaticBlock.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
7192
+ StaticBlock.prototype.applyDeoptimizations = doNotDeoptimize;
6956
7193
  function isStaticBlock(statement) {
6957
7194
  return statement.type === parseAst_js.StaticBlock;
6958
7195
  }
6959
7196
 
6960
- class ObjectMember extends ExpressionEntity {
6961
- constructor(object, key) {
6962
- super();
6963
- this.object = object;
6964
- this.key = key;
6965
- }
6966
- deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
6967
- this.object.deoptimizeArgumentsOnInteractionAtPath(interaction, [this.key, ...path], recursionTracker);
6968
- }
6969
- deoptimizePath(path) {
6970
- this.object.deoptimizePath([this.key, ...path]);
6971
- }
6972
- getLiteralValueAtPath(path, recursionTracker, origin) {
6973
- return this.object.getLiteralValueAtPath([this.key, ...path], recursionTracker, origin);
6974
- }
6975
- getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin) {
6976
- return this.object.getReturnExpressionWhenCalledAtPath([this.key, ...path], interaction, recursionTracker, origin);
6977
- }
6978
- hasEffectsOnInteractionAtPath(path, interaction, context) {
6979
- return this.object.hasEffectsOnInteractionAtPath([this.key, ...path], interaction, context);
6980
- }
6981
- }
6982
-
6983
7197
  class ClassNode extends NodeBase {
6984
7198
  constructor() {
6985
7199
  super(...arguments);
@@ -7020,21 +7234,20 @@ class ClassNode extends NodeBase {
7020
7234
  : this.getObjectEntity().hasEffectsOnInteractionAtPath(path, interaction, context);
7021
7235
  }
7022
7236
  include(context, includeChildrenRecursively) {
7023
- if (!this.deoptimized)
7024
- this.applyDeoptimizations();
7025
- this.included = true;
7237
+ if (!this.included)
7238
+ this.includeNode(context);
7026
7239
  this.superClass?.include(context, includeChildrenRecursively);
7027
7240
  this.body.include(context, includeChildrenRecursively);
7028
7241
  for (const decorator of this.decorators)
7029
7242
  decorator.include(context, includeChildrenRecursively);
7030
7243
  if (this.id) {
7031
7244
  this.id.markDeclarationReached();
7032
- this.id.include();
7245
+ this.id.include(context);
7033
7246
  }
7034
7247
  }
7035
7248
  initialise() {
7036
7249
  super.initialise();
7037
- this.id?.declare('class', this);
7250
+ this.id?.declare('class', EMPTY_PATH, this);
7038
7251
  for (const method of this.body.body) {
7039
7252
  if (method instanceof MethodDefinition && method.kind === 'constructor') {
7040
7253
  this.classConstructor = method;
@@ -7092,11 +7305,12 @@ class ClassNode extends NodeBase {
7092
7305
  staticProperties.unshift({
7093
7306
  key: 'prototype',
7094
7307
  kind: 'init',
7095
- property: new ObjectEntity(dynamicMethods, this.superClass ? new ObjectMember(this.superClass, 'prototype') : OBJECT_PROTOTYPE)
7308
+ property: new ObjectEntity(dynamicMethods, this.superClass ? new ObjectMember(this.superClass, ['prototype']) : OBJECT_PROTOTYPE)
7096
7309
  });
7097
7310
  return (this.objectEntity = new ObjectEntity(staticProperties, this.superClass || OBJECT_PROTOTYPE));
7098
7311
  }
7099
7312
  }
7313
+ ClassNode.prototype.includeNode = onlyIncludeSelf;
7100
7314
 
7101
7315
  class ClassDeclaration extends ClassNode {
7102
7316
  initialise() {
@@ -7149,7 +7363,7 @@ class ClassDeclaration extends ClassNode {
7149
7363
 
7150
7364
  class ArgumentsVariable extends LocalVariable {
7151
7365
  constructor(context) {
7152
- super('arguments', null, UNKNOWN_EXPRESSION, context, 'other');
7366
+ super('arguments', null, UNKNOWN_EXPRESSION, EMPTY_PATH, context, 'other');
7153
7367
  this.deoptimizedArguments = [];
7154
7368
  }
7155
7369
  addArgumentToBeDeoptimized(argument) {
@@ -7163,8 +7377,8 @@ class ArgumentsVariable extends LocalVariable {
7163
7377
  hasEffectsOnInteractionAtPath(path, { type }) {
7164
7378
  return type !== INTERACTION_ACCESSED || path.length > 1;
7165
7379
  }
7166
- include() {
7167
- super.include();
7380
+ includePath(path, context) {
7381
+ super.includePath(path, context);
7168
7382
  for (const argument of this.deoptimizedArguments) {
7169
7383
  argument.deoptimizePath(UNKNOWN_PATH);
7170
7384
  }
@@ -7172,30 +7386,31 @@ class ArgumentsVariable extends LocalVariable {
7172
7386
  }
7173
7387
  }
7174
7388
 
7175
- const MAX_TRACKED_INTERACTIONS = 20;
7389
+ const MAX_TRACKED_INTERACTIONS = 10;
7390
+ const MAX_DEOPTIMIZED_FIELDS = 5;
7176
7391
  const NO_INTERACTIONS = parseAst_js.EMPTY_ARRAY;
7177
7392
  const UNKNOWN_DEOPTIMIZED_FIELD = new Set([UnknownKey]);
7178
- const EMPTY_PATH_TRACKER = new PathTracker();
7393
+ const EMPTY_PATH_TRACKER = new EntityPathTracker();
7179
7394
  const UNKNOWN_DEOPTIMIZED_ENTITY = new Set([UNKNOWN_EXPRESSION]);
7180
7395
  class ParameterVariable extends LocalVariable {
7181
- constructor(name, declarator, context) {
7182
- super(name, declarator, UNKNOWN_EXPRESSION, context, 'parameter');
7396
+ constructor(name, declarator, argumentPath, context) {
7397
+ super(name, declarator, UNKNOWN_EXPRESSION, argumentPath, context, 'parameter');
7398
+ this.argumentsToBeDeoptimized = new Set();
7183
7399
  this.deoptimizationInteractions = [];
7184
- this.deoptimizations = new PathTracker();
7400
+ this.deoptimizations = new EntityPathTracker();
7185
7401
  this.deoptimizedFields = new Set();
7186
- this.entitiesToBeDeoptimized = new Set();
7187
- this.expressionsUseTheKnownValue = [];
7402
+ this.expressionsDependingOnKnownValue = [];
7188
7403
  this.knownValue = null;
7189
7404
  this.knownValueLiteral = UnknownValue;
7190
- this.frozenValue = null;
7191
7405
  }
7192
- addEntityToBeDeoptimized(entity) {
7406
+ addArgumentValue(entity) {
7407
+ this.updateKnownValue(entity);
7193
7408
  if (entity === UNKNOWN_EXPRESSION) {
7194
7409
  // As unknown expressions fully deoptimize all interactions, we can clear
7195
7410
  // the interaction cache at this point provided we keep this optimization
7196
7411
  // in mind when adding new interactions
7197
- if (!this.entitiesToBeDeoptimized.has(UNKNOWN_EXPRESSION)) {
7198
- this.entitiesToBeDeoptimized.add(UNKNOWN_EXPRESSION);
7412
+ if (!this.argumentsToBeDeoptimized.has(UNKNOWN_EXPRESSION)) {
7413
+ this.argumentsToBeDeoptimized.add(UNKNOWN_EXPRESSION);
7199
7414
  for (const { interaction } of this.deoptimizationInteractions) {
7200
7415
  deoptimizeInteraction(interaction);
7201
7416
  }
@@ -7205,27 +7420,30 @@ class ParameterVariable extends LocalVariable {
7205
7420
  else if (this.deoptimizedFields.has(UnknownKey)) {
7206
7421
  // This means that we already deoptimized all interactions and no longer
7207
7422
  // track them
7208
- entity.deoptimizePath(UNKNOWN_PATH);
7423
+ entity.deoptimizePath([...this.initPath, UnknownKey]);
7209
7424
  }
7210
- else if (!this.entitiesToBeDeoptimized.has(entity)) {
7211
- this.entitiesToBeDeoptimized.add(entity);
7425
+ else if (!this.argumentsToBeDeoptimized.has(entity)) {
7426
+ this.argumentsToBeDeoptimized.add(entity);
7212
7427
  for (const field of this.deoptimizedFields) {
7213
- entity.deoptimizePath([field]);
7428
+ entity.deoptimizePath([...this.initPath, field]);
7214
7429
  }
7215
7430
  for (const { interaction, path } of this.deoptimizationInteractions) {
7216
- entity.deoptimizeArgumentsOnInteractionAtPath(interaction, path, SHARED_RECURSION_TRACKER);
7431
+ entity.deoptimizeArgumentsOnInteractionAtPath(interaction, [...this.initPath, ...path], SHARED_RECURSION_TRACKER);
7217
7432
  }
7218
7433
  }
7219
7434
  }
7435
+ /** This says we should not make assumptions about the value of the parameter.
7436
+ * This is different from deoptimization that will also cause argument values
7437
+ * to be deoptimized. */
7220
7438
  markReassigned() {
7221
7439
  if (this.isReassigned) {
7222
7440
  return;
7223
7441
  }
7224
7442
  super.markReassigned();
7225
- for (const expression of this.expressionsUseTheKnownValue) {
7443
+ for (const expression of this.expressionsDependingOnKnownValue) {
7226
7444
  expression.deoptimizeCache();
7227
7445
  }
7228
- this.expressionsUseTheKnownValue = parseAst_js.EMPTY_ARRAY;
7446
+ this.expressionsDependingOnKnownValue = parseAst_js.EMPTY_ARRAY;
7229
7447
  }
7230
7448
  deoptimizeCache() {
7231
7449
  this.markReassigned();
@@ -7242,7 +7460,7 @@ class ParameterVariable extends LocalVariable {
7242
7460
  }
7243
7461
  if (this.knownValue === null) {
7244
7462
  this.knownValue = argument;
7245
- this.knownValueLiteral = argument.getLiteralValueAtPath(EMPTY_PATH, SHARED_RECURSION_TRACKER, this);
7463
+ this.knownValueLiteral = argument.getLiteralValueAtPath(this.initPath, SHARED_RECURSION_TRACKER, this);
7246
7464
  return;
7247
7465
  }
7248
7466
  // the same literal or identifier, do nothing
@@ -7252,14 +7470,10 @@ class ParameterVariable extends LocalVariable {
7252
7470
  this.knownValue.variable === argument.variable)) {
7253
7471
  return;
7254
7472
  }
7255
- const oldValue = this.knownValueLiteral;
7256
- if (typeof oldValue === 'symbol') {
7257
- this.markReassigned();
7258
- return;
7259
- }
7260
- // add tracking for the new argument
7261
- const newValue = argument.getLiteralValueAtPath(EMPTY_PATH, SHARED_RECURSION_TRACKER, this);
7262
- if (newValue !== oldValue) {
7473
+ const { knownValueLiteral } = this;
7474
+ if (typeof knownValueLiteral === 'symbol' ||
7475
+ argument.getLiteralValueAtPath(this.initPath, SHARED_RECURSION_TRACKER, this) !==
7476
+ knownValueLiteral) {
7263
7477
  this.markReassigned();
7264
7478
  }
7265
7479
  }
@@ -7270,42 +7484,47 @@ class ParameterVariable extends LocalVariable {
7270
7484
  * @returns the frozen value
7271
7485
  */
7272
7486
  getKnownValue() {
7273
- if (this.frozenValue === null) {
7274
- this.frozenValue = this.knownValue || UNKNOWN_EXPRESSION;
7275
- }
7276
- return this.frozenValue;
7487
+ return this.knownValue || UNKNOWN_EXPRESSION;
7277
7488
  }
7278
7489
  getLiteralValueAtPath(path, recursionTracker, origin) {
7279
- if (this.isReassigned) {
7490
+ if (this.isReassigned || path.length + this.initPath.length > MAX_PATH_DEPTH) {
7280
7491
  return UnknownValue;
7281
7492
  }
7282
7493
  const knownValue = this.getKnownValue();
7283
- this.expressionsUseTheKnownValue.push(origin);
7284
- return recursionTracker.withTrackedEntityAtPath(path, knownValue, () => knownValue.getLiteralValueAtPath(path, recursionTracker, origin), UnknownValue);
7494
+ this.expressionsDependingOnKnownValue.push(origin);
7495
+ return recursionTracker.withTrackedEntityAtPath(path, knownValue, () => knownValue.getLiteralValueAtPath([...this.initPath, ...path], recursionTracker, origin), UnknownValue);
7285
7496
  }
7286
7497
  hasEffectsOnInteractionAtPath(path, interaction, context) {
7287
- if (this.isReassigned || interaction.type === INTERACTION_ASSIGNED) {
7498
+ const { type } = interaction;
7499
+ if (this.isReassigned ||
7500
+ type === INTERACTION_ASSIGNED ||
7501
+ path.length + this.initPath.length > MAX_PATH_DEPTH) {
7288
7502
  return super.hasEffectsOnInteractionAtPath(path, interaction, context);
7289
7503
  }
7290
- const knownValue = this.getKnownValue();
7291
- return knownValue.hasEffectsOnInteractionAtPath(path, interaction, context);
7504
+ return (!(type === INTERACTION_CALLED
7505
+ ? (interaction.withNew
7506
+ ? context.instantiated
7507
+ : context.called).trackEntityAtPathAndGetIfTracked(path, interaction.args, this)
7508
+ : context.accessed.trackEntityAtPathAndGetIfTracked(path, this)) &&
7509
+ this.getKnownValue().hasEffectsOnInteractionAtPath([...this.initPath, ...path], interaction, context));
7292
7510
  }
7293
7511
  deoptimizeArgumentsOnInteractionAtPath(interaction, path) {
7294
7512
  // For performance reasons, we fully deoptimize all deeper interactions
7295
7513
  if (path.length >= 2 ||
7296
- this.entitiesToBeDeoptimized.has(UNKNOWN_EXPRESSION) ||
7514
+ this.argumentsToBeDeoptimized.has(UNKNOWN_EXPRESSION) ||
7297
7515
  this.deoptimizationInteractions.length >= MAX_TRACKED_INTERACTIONS ||
7298
7516
  (path.length === 1 &&
7299
7517
  (this.deoptimizedFields.has(UnknownKey) ||
7300
- (interaction.type === INTERACTION_CALLED && this.deoptimizedFields.has(path[0]))))) {
7518
+ (interaction.type === INTERACTION_CALLED && this.deoptimizedFields.has(path[0])))) ||
7519
+ this.initPath.length + path.length > MAX_PATH_DEPTH) {
7301
7520
  deoptimizeInteraction(interaction);
7302
7521
  return;
7303
7522
  }
7304
7523
  if (!this.deoptimizations.trackEntityAtPathAndGetIfTracked(path, interaction.args)) {
7305
- for (const entity of this.entitiesToBeDeoptimized) {
7306
- entity.deoptimizeArgumentsOnInteractionAtPath(interaction, path, SHARED_RECURSION_TRACKER);
7524
+ for (const entity of this.argumentsToBeDeoptimized) {
7525
+ entity.deoptimizeArgumentsOnInteractionAtPath(interaction, [...this.initPath, ...path], SHARED_RECURSION_TRACKER);
7307
7526
  }
7308
- if (!this.entitiesToBeDeoptimized.has(UNKNOWN_EXPRESSION)) {
7527
+ if (!this.argumentsToBeDeoptimized.has(UNKNOWN_EXPRESSION)) {
7309
7528
  this.deoptimizationInteractions.push({
7310
7529
  interaction,
7311
7530
  path
@@ -7321,22 +7540,27 @@ class ParameterVariable extends LocalVariable {
7321
7540
  if (this.deoptimizedFields.has(UnknownKey)) {
7322
7541
  return;
7323
7542
  }
7324
- const key = path[0];
7543
+ let key = path[0];
7325
7544
  if (this.deoptimizedFields.has(key)) {
7326
7545
  return;
7327
7546
  }
7328
- this.deoptimizedFields.add(key);
7329
- for (const entity of this.entitiesToBeDeoptimized) {
7547
+ if (this.deoptimizedFields.size > MAX_DEOPTIMIZED_FIELDS) {
7548
+ key = UnknownKey;
7549
+ }
7550
+ else {
7551
+ this.deoptimizedFields.add(key);
7552
+ }
7553
+ for (const entity of this.argumentsToBeDeoptimized) {
7330
7554
  // We do not need a recursion tracker here as we already track whether
7331
7555
  // this field is deoptimized
7332
- entity.deoptimizePath([key]);
7556
+ entity.deoptimizePath([...this.initPath, key]);
7333
7557
  }
7334
7558
  if (key === UnknownKey) {
7335
7559
  // save some memory
7336
7560
  this.deoptimizationInteractions = NO_INTERACTIONS;
7337
7561
  this.deoptimizations = EMPTY_PATH_TRACKER;
7338
7562
  this.deoptimizedFields = UNKNOWN_DEOPTIMIZED_FIELD;
7339
- this.entitiesToBeDeoptimized = UNKNOWN_DEOPTIMIZED_ENTITY;
7563
+ this.argumentsToBeDeoptimized = UNKNOWN_DEOPTIMIZED_ENTITY;
7340
7564
  }
7341
7565
  }
7342
7566
  getReturnExpressionWhenCalledAtPath(path) {
@@ -7351,11 +7575,14 @@ class ParameterVariable extends LocalVariable {
7351
7575
  }
7352
7576
  return UNKNOWN_RETURN_EXPRESSION;
7353
7577
  }
7578
+ includeArgumentPaths(entity, context) {
7579
+ this.includedPathTracker.includeAllPaths(entity, context, this.initPath);
7580
+ }
7354
7581
  }
7355
7582
 
7356
7583
  class ThisVariable extends ParameterVariable {
7357
7584
  constructor(context) {
7358
- super('this', null, context);
7585
+ super('this', null, EMPTY_PATH, context);
7359
7586
  }
7360
7587
  hasEffectsOnInteractionAtPath(path, interaction, context) {
7361
7588
  return (context.replacedVariableInits.get(this) || UNKNOWN_EXPRESSION).hasEffectsOnInteractionAtPath(path, interaction, context);
@@ -7367,7 +7594,7 @@ class CatchBodyScope extends ChildScope {
7367
7594
  super(parent, parent.context);
7368
7595
  this.parent = parent;
7369
7596
  }
7370
- addDeclaration(identifier, context, init, kind) {
7597
+ addDeclaration(identifier, context, init, destructuredInitPath, kind) {
7371
7598
  if (kind === 'var') {
7372
7599
  const name = identifier.name;
7373
7600
  const existingVariable = this.hoistedVariables?.get(name) || this.variables.get(name);
@@ -7380,7 +7607,7 @@ class CatchBodyScope extends ChildScope {
7380
7607
  // the assignment actually goes to the parameter and the var is
7381
7608
  // hoisted without assignment. Locally, it is shadowed by the
7382
7609
  // parameter
7383
- const declaredVariable = this.parent.parent.addDeclaration(identifier, context, UNDEFINED_EXPRESSION, kind);
7610
+ const declaredVariable = this.parent.parent.addDeclaration(identifier, context, UNDEFINED_EXPRESSION, destructuredInitPath, kind);
7384
7611
  // To avoid the need to rewrite the declaration, we link the variable
7385
7612
  // names. If we ever implement a logic that splits initialization and
7386
7613
  // assignment for hoisted vars, the "renderLikeHoisted" logic can be
@@ -7399,7 +7626,7 @@ class CatchBodyScope extends ChildScope {
7399
7626
  return context.error(parseAst_js.logRedeclarationError(name), identifier.start);
7400
7627
  }
7401
7628
  // We only add parameters to parameter scopes
7402
- const declaredVariable = this.parent.parent.addDeclaration(identifier, context, init, kind);
7629
+ const declaredVariable = this.parent.parent.addDeclaration(identifier, context, init, destructuredInitPath, kind);
7403
7630
  // Necessary to make sure the init is deoptimized for conditional declarations.
7404
7631
  // We cannot call deoptimizePath here.
7405
7632
  declaredVariable.markInitializersForDeoptimization();
@@ -7407,7 +7634,7 @@ class CatchBodyScope extends ChildScope {
7407
7634
  this.addHoistedVariable(name, declaredVariable);
7408
7635
  return declaredVariable;
7409
7636
  }
7410
- return super.addDeclaration(identifier, context, init, kind);
7637
+ return super.addDeclaration(identifier, context, init, destructuredInitPath, kind);
7411
7638
  }
7412
7639
  }
7413
7640
 
@@ -7417,7 +7644,7 @@ class FunctionBodyScope extends ChildScope {
7417
7644
  }
7418
7645
  // There is stuff that is only allowed in function scopes, i.e. functions can
7419
7646
  // be redeclared, functions and var can redeclare each other
7420
- addDeclaration(identifier, context, init, kind) {
7647
+ addDeclaration(identifier, context, init, destructuredInitPath, kind) {
7421
7648
  const name = identifier.name;
7422
7649
  const existingVariable = this.hoistedVariables?.get(name) || this.variables.get(name);
7423
7650
  if (existingVariable) {
@@ -7429,7 +7656,7 @@ class FunctionBodyScope extends ChildScope {
7429
7656
  }
7430
7657
  context.error(parseAst_js.logRedeclarationError(name), identifier.start);
7431
7658
  }
7432
- const newVariable = new LocalVariable(identifier.name, identifier, init, context, kind);
7659
+ const newVariable = new LocalVariable(identifier.name, identifier, init, destructuredInitPath, context, kind);
7433
7660
  this.variables.set(name, newVariable);
7434
7661
  return newVariable;
7435
7662
  }
@@ -7438,21 +7665,21 @@ class FunctionBodyScope extends ChildScope {
7438
7665
  class ParameterScope extends ChildScope {
7439
7666
  constructor(parent, isCatchScope) {
7440
7667
  super(parent, parent.context);
7441
- this.parameters = [];
7442
7668
  this.hasRest = false;
7669
+ this.parameters = [];
7443
7670
  this.bodyScope = isCatchScope ? new CatchBodyScope(this) : new FunctionBodyScope(this);
7444
7671
  }
7445
7672
  /**
7446
7673
  * Adds a parameter to this scope. Parameters must be added in the correct
7447
7674
  * order, i.e. from left to right.
7448
7675
  */
7449
- addParameterDeclaration(identifier) {
7676
+ addParameterDeclaration(identifier, argumentPath) {
7450
7677
  const { name, start } = identifier;
7451
7678
  const existingParameter = this.variables.get(name);
7452
7679
  if (existingParameter) {
7453
7680
  return this.context.error(parseAst_js.logDuplicateArgumentNameError(name), start);
7454
7681
  }
7455
- const variable = new ParameterVariable(name, identifier, this.context);
7682
+ const variable = new ParameterVariable(name, identifier, argumentPath, this.context);
7456
7683
  this.variables.set(name, variable);
7457
7684
  // We also add it to the body scope to detect name conflicts with local
7458
7685
  // variables. We still need the intermediate scope, though, as parameter
@@ -7470,42 +7697,56 @@ class ParameterScope extends ChildScope {
7470
7697
  }
7471
7698
  this.hasRest = hasRest;
7472
7699
  }
7473
- includeCallArguments(context, parameters) {
7700
+ includeCallArguments(context, interaction) {
7474
7701
  let calledFromTryStatement = false;
7475
7702
  let argumentIncluded = false;
7476
7703
  const restParameter = this.hasRest && this.parameters[this.parameters.length - 1];
7477
- for (const checkedArgument of parameters) {
7478
- if (checkedArgument instanceof SpreadElement) {
7479
- for (const argument of parameters) {
7480
- argument.include(context, false);
7481
- }
7482
- break;
7704
+ const { args } = interaction;
7705
+ let lastExplicitlyIncludedIndex = args.length - 1;
7706
+ // If there is a SpreadElement, we need to include all arguments after it
7707
+ // because we no longer know which argument corresponds to which parameter.
7708
+ for (let argumentIndex = 1; argumentIndex < args.length; argumentIndex++) {
7709
+ const argument = args[argumentIndex];
7710
+ if (argument instanceof SpreadElement && !argumentIncluded) {
7711
+ argumentIncluded = true;
7712
+ lastExplicitlyIncludedIndex = argumentIndex - 1;
7713
+ }
7714
+ if (argumentIncluded) {
7715
+ argument.includePath(UNKNOWN_PATH, context);
7716
+ argument.include(context, false);
7483
7717
  }
7484
7718
  }
7485
- for (let index = parameters.length - 1; index >= 0; index--) {
7486
- const parameterVariables = this.parameters[index] || restParameter;
7487
- const argument = parameters[index];
7719
+ // Now we go backwards either starting from the last argument or before the
7720
+ // first SpreadElement to ensure all arguments before are included as needed
7721
+ for (let index = lastExplicitlyIncludedIndex; index >= 1; index--) {
7722
+ const parameterVariables = this.parameters[index - 1] || restParameter;
7723
+ const argument = args[index];
7488
7724
  if (parameterVariables) {
7489
7725
  calledFromTryStatement = false;
7490
7726
  if (parameterVariables.length === 0) {
7491
- // handle empty destructuring
7727
+ // handle empty destructuring to avoid destructuring undefined
7492
7728
  argumentIncluded = true;
7493
7729
  }
7494
7730
  else {
7495
7731
  for (const variable of parameterVariables) {
7496
- if (variable.included) {
7497
- argumentIncluded = true;
7498
- }
7499
7732
  if (variable.calledFromTryStatement) {
7500
7733
  calledFromTryStatement = true;
7501
7734
  }
7735
+ if (variable.included) {
7736
+ argumentIncluded = true;
7737
+ if (calledFromTryStatement) {
7738
+ argument.include(context, true);
7739
+ }
7740
+ else {
7741
+ variable.includeArgumentPaths(argument, context);
7742
+ argument.include(context, false);
7743
+ }
7744
+ }
7502
7745
  }
7503
7746
  }
7504
7747
  }
7505
- if (!argumentIncluded && argument.shouldBeIncluded(context)) {
7748
+ if (!argument.included && (argumentIncluded || argument.shouldBeIncluded(context))) {
7506
7749
  argumentIncluded = true;
7507
- }
7508
- if (argumentIncluded) {
7509
7750
  argument.include(context, calledFromTryStatement);
7510
7751
  }
7511
7752
  }
@@ -7521,11 +7762,62 @@ class ReturnValueScope extends ParameterScope {
7521
7762
  addReturnExpression(expression) {
7522
7763
  this.returnExpressions.push(expression);
7523
7764
  }
7765
+ deoptimizeArgumentsOnCall(interaction) {
7766
+ const { parameters } = this;
7767
+ const { args } = interaction;
7768
+ let position = 0;
7769
+ for (; position < args.length - 1; position++) {
7770
+ // Only the "this" argument arg[0] can be null
7771
+ const argument = args[position + 1];
7772
+ if (argument instanceof SpreadElement) {
7773
+ // This deoptimizes the current and remaining parameters and arguments
7774
+ for (; position < parameters.length; position++) {
7775
+ args[position + 1]?.deoptimizePath(UNKNOWN_PATH);
7776
+ parameters[position].forEach(variable => variable.markReassigned());
7777
+ }
7778
+ break;
7779
+ }
7780
+ if (this.hasRest && position >= parameters.length - 1) {
7781
+ argument.deoptimizePath(UNKNOWN_PATH);
7782
+ }
7783
+ else {
7784
+ const variables = parameters[position];
7785
+ if (variables) {
7786
+ for (const variable of variables) {
7787
+ variable.addArgumentValue(argument);
7788
+ }
7789
+ }
7790
+ this.addArgumentToBeDeoptimized(argument);
7791
+ }
7792
+ }
7793
+ const nonRestParameterLength = this.hasRest ? parameters.length - 1 : parameters.length;
7794
+ for (; position < nonRestParameterLength; position++) {
7795
+ for (const variable of parameters[position]) {
7796
+ variable.addArgumentValue(UNDEFINED_EXPRESSION);
7797
+ }
7798
+ }
7799
+ }
7524
7800
  getReturnExpression() {
7525
7801
  if (this.returnExpression === null)
7526
7802
  this.updateReturnExpression();
7527
7803
  return this.returnExpression;
7528
7804
  }
7805
+ deoptimizeAllParameters() {
7806
+ for (const parameter of this.parameters) {
7807
+ for (const variable of parameter) {
7808
+ variable.deoptimizePath(UNKNOWN_PATH);
7809
+ variable.markReassigned();
7810
+ }
7811
+ }
7812
+ }
7813
+ reassignAllParameters() {
7814
+ for (const parameter of this.parameters) {
7815
+ for (const variable of parameter) {
7816
+ variable.markReassigned();
7817
+ }
7818
+ }
7819
+ }
7820
+ addArgumentToBeDeoptimized(_argument) { }
7529
7821
  updateReturnExpression() {
7530
7822
  if (this.returnExpressions.length === 1) {
7531
7823
  this.returnExpression = this.returnExpressions[0];
@@ -7541,24 +7833,30 @@ class ReturnValueScope extends ParameterScope {
7541
7833
 
7542
7834
  class FunctionScope extends ReturnValueScope {
7543
7835
  constructor(parent) {
7544
- const { context } = parent;
7545
7836
  super(parent, false);
7837
+ const { context } = parent;
7546
7838
  this.variables.set('arguments', (this.argumentsVariable = new ArgumentsVariable(context)));
7547
7839
  this.variables.set('this', (this.thisVariable = new ThisVariable(context)));
7548
7840
  }
7549
7841
  findLexicalBoundary() {
7550
7842
  return this;
7551
7843
  }
7552
- includeCallArguments(context, parameters) {
7553
- super.includeCallArguments(context, parameters);
7844
+ includeCallArguments(context, interaction) {
7845
+ super.includeCallArguments(context, interaction);
7554
7846
  if (this.argumentsVariable.included) {
7555
- for (const argument of parameters) {
7556
- if (!argument.included) {
7847
+ const { args } = interaction;
7848
+ for (let argumentIndex = 1; argumentIndex < args.length; argumentIndex++) {
7849
+ const argument = args[argumentIndex];
7850
+ if (argument) {
7851
+ argument.includePath(UNKNOWN_PATH, context);
7557
7852
  argument.include(context, false);
7558
7853
  }
7559
7854
  }
7560
7855
  }
7561
7856
  }
7857
+ addArgumentToBeDeoptimized(argument) {
7858
+ this.argumentsVariable.addArgumentToBeDeoptimized(argument);
7859
+ }
7562
7860
  }
7563
7861
 
7564
7862
  class ExpressionStatement extends NodeBase {
@@ -7586,8 +7884,9 @@ class ExpressionStatement extends NodeBase {
7586
7884
  return this.parent.type !== parseAst_js.Program;
7587
7885
  return super.shouldBeIncluded(context);
7588
7886
  }
7589
- applyDeoptimizations() { }
7590
7887
  }
7888
+ ExpressionStatement.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
7889
+ ExpressionStatement.prototype.applyDeoptimizations = doNotDeoptimize;
7591
7890
 
7592
7891
  class BlockStatement extends NodeBase {
7593
7892
  get deoptimizeBody() {
@@ -7652,6 +7951,8 @@ class BlockStatement extends NodeBase {
7652
7951
  }
7653
7952
  }
7654
7953
  }
7954
+ BlockStatement.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
7955
+ BlockStatement.prototype.applyDeoptimizations = doNotDeoptimize;
7655
7956
 
7656
7957
  class RestElement extends NodeBase {
7657
7958
  constructor() {
@@ -7661,9 +7962,12 @@ class RestElement extends NodeBase {
7661
7962
  addExportedVariables(variables, exportNamesByVariable) {
7662
7963
  this.argument.addExportedVariables(variables, exportNamesByVariable);
7663
7964
  }
7664
- declare(kind, init) {
7965
+ declare(kind, destructuredInitPath, init) {
7665
7966
  this.declarationInit = init;
7666
- return this.argument.declare(kind, UNKNOWN_EXPRESSION);
7967
+ return this.argument.declare(kind, getIncludedPatternPath$1(destructuredInitPath), init);
7968
+ }
7969
+ deoptimizeAssignment(destructuredInitPath, init) {
7970
+ this.argument.deoptimizeAssignment(getIncludedPatternPath$1(destructuredInitPath), init);
7667
7971
  }
7668
7972
  deoptimizePath(path) {
7669
7973
  if (path.length === 0) {
@@ -7674,6 +7978,20 @@ class RestElement extends NodeBase {
7674
7978
  return (path.length > 0 ||
7675
7979
  this.argument.hasEffectsOnInteractionAtPath(EMPTY_PATH, interaction, context));
7676
7980
  }
7981
+ hasEffectsWhenDestructuring(context, destructuredInitPath, init) {
7982
+ return this.argument.hasEffectsWhenDestructuring(context, getIncludedPatternPath$1(destructuredInitPath), init);
7983
+ }
7984
+ includeDestructuredIfNecessary(context, destructuredInitPath, init) {
7985
+ return (this.included =
7986
+ this.argument.includeDestructuredIfNecessary(context, getIncludedPatternPath$1(destructuredInitPath), init) || this.included);
7987
+ }
7988
+ include(context, includeChildrenRecursively) {
7989
+ if (!this.included)
7990
+ this.includeNode(context);
7991
+ // This should just include the identifier, its properties should be
7992
+ // included where the variable is used.
7993
+ this.argument.include(context, includeChildrenRecursively);
7994
+ }
7677
7995
  markDeclarationReached() {
7678
7996
  this.argument.markDeclarationReached();
7679
7997
  }
@@ -7685,12 +8003,16 @@ class RestElement extends NodeBase {
7685
8003
  }
7686
8004
  }
7687
8005
  }
8006
+ RestElement.prototype.includeNode = onlyIncludeSelf;
8007
+ const getIncludedPatternPath$1 = (destructuredInitPath) => destructuredInitPath.at(-1) === UnknownKey
8008
+ ? destructuredInitPath
8009
+ : [...destructuredInitPath, UnknownKey];
7688
8010
 
7689
8011
  class FunctionBase extends NodeBase {
7690
8012
  constructor() {
7691
8013
  super(...arguments);
7692
- this.objectEntity = null;
7693
8014
  this.parameterVariableValuesDeoptimized = false;
8015
+ this.includeCallArguments = this.scope.includeCallArguments.bind(this.scope);
7694
8016
  }
7695
8017
  get async() {
7696
8018
  return isFlagSet(this.flags, 256 /* Flag.async */);
@@ -7710,53 +8032,15 @@ class FunctionBase extends NodeBase {
7710
8032
  set generator(value) {
7711
8033
  this.flags = setFlag(this.flags, 4194304 /* Flag.generator */, value);
7712
8034
  }
7713
- updateParameterVariableValues(_arguments) {
7714
- for (let position = 0; position < this.params.length; position++) {
7715
- const parameter = this.params[position];
7716
- if (!(parameter instanceof Identifier)) {
7717
- continue;
7718
- }
7719
- const parameterVariable = parameter.variable;
7720
- const argument = _arguments[position + 1] ?? UNDEFINED_EXPRESSION;
7721
- parameterVariable.updateKnownValue(argument);
7722
- }
8035
+ get hasCachedEffects() {
8036
+ return isFlagSet(this.flags, 67108864 /* Flag.hasEffects */);
7723
8037
  }
7724
- deoptimizeParameterVariableValues() {
7725
- for (const parameter of this.params) {
7726
- if (parameter instanceof Identifier) {
7727
- const parameterVariable = parameter.variable;
7728
- parameterVariable.markReassigned();
7729
- }
7730
- }
8038
+ set hasCachedEffects(value) {
8039
+ this.flags = setFlag(this.flags, 67108864 /* Flag.hasEffects */, value);
7731
8040
  }
7732
8041
  deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
7733
- if (interaction.type === INTERACTION_CALLED) {
7734
- const { parameters } = this.scope;
7735
- const { args } = interaction;
7736
- let hasRest = false;
7737
- for (let position = 0; position < args.length - 1; position++) {
7738
- const parameter = this.params[position];
7739
- // Only the "this" argument arg[0] can be null
7740
- const argument = args[position + 1];
7741
- if (argument instanceof SpreadElement) {
7742
- this.deoptimizeParameterVariableValues();
7743
- }
7744
- if (hasRest || parameter instanceof RestElement) {
7745
- hasRest = true;
7746
- argument.deoptimizePath(UNKNOWN_PATH);
7747
- }
7748
- else if (parameter instanceof Identifier) {
7749
- parameters[position][0].addEntityToBeDeoptimized(argument);
7750
- this.addArgumentToBeDeoptimized(argument);
7751
- }
7752
- else if (parameter) {
7753
- argument.deoptimizePath(UNKNOWN_PATH);
7754
- }
7755
- else {
7756
- this.addArgumentToBeDeoptimized(argument);
7757
- }
7758
- }
7759
- this.updateParameterVariableValues(args);
8042
+ if (interaction.type === INTERACTION_CALLED && path.length === 0) {
8043
+ this.scope.deoptimizeArgumentsOnCall(interaction);
7760
8044
  }
7761
8045
  else {
7762
8046
  this.getObjectEntity().deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker);
@@ -7768,12 +8052,7 @@ class FunctionBase extends NodeBase {
7768
8052
  // A reassignment of UNKNOWN_PATH is considered equivalent to having lost track
7769
8053
  // which means the return expression and parameters need to be reassigned
7770
8054
  this.scope.getReturnExpression().deoptimizePath(UNKNOWN_PATH);
7771
- for (const parameterList of this.scope.parameters) {
7772
- for (const parameter of parameterList) {
7773
- parameter.deoptimizePath(UNKNOWN_PATH);
7774
- parameter.markReassigned();
7775
- }
7776
- }
8055
+ this.scope.deoptimizeAllParameters();
7777
8056
  }
7778
8057
  }
7779
8058
  getLiteralValueAtPath(path, recursionTracker, origin) {
@@ -7797,8 +8076,8 @@ class FunctionBase extends NodeBase {
7797
8076
  if (path.length > 0 || interaction.type !== INTERACTION_CALLED) {
7798
8077
  return this.getObjectEntity().hasEffectsOnInteractionAtPath(path, interaction, context);
7799
8078
  }
7800
- if (this.annotationNoSideEffects) {
7801
- return false;
8079
+ if (this.hasCachedEffects) {
8080
+ return true;
7802
8081
  }
7803
8082
  if (this.async) {
7804
8083
  const { propertyReadSideEffects } = this.scope.context.options
@@ -7808,12 +8087,20 @@ class FunctionBase extends NodeBase {
7808
8087
  (propertyReadSideEffects &&
7809
8088
  (propertyReadSideEffects === 'always' ||
7810
8089
  returnExpression.hasEffectsOnInteractionAtPath(['then'], NODE_INTERACTION_UNKNOWN_ACCESS, context)))) {
8090
+ this.hasCachedEffects = true;
7811
8091
  return true;
7812
8092
  }
7813
8093
  }
7814
- for (const parameter of this.params) {
7815
- if (parameter.hasEffects(context))
8094
+ const { propertyReadSideEffects } = this.scope.context.options
8095
+ .treeshake;
8096
+ for (let index = 0; index < this.params.length; index++) {
8097
+ const parameter = this.params[index];
8098
+ if (parameter.hasEffects(context) ||
8099
+ (propertyReadSideEffects &&
8100
+ parameter.hasEffectsWhenDestructuring(context, EMPTY_PATH, interaction.args[index + 1] || UNDEFINED_EXPRESSION))) {
8101
+ this.hasCachedEffects = true;
7816
8102
  return true;
8103
+ }
7817
8104
  }
7818
8105
  return false;
7819
8106
  }
@@ -7831,21 +8118,17 @@ class FunctionBase extends NodeBase {
7831
8118
  return variable?.getOnlyFunctionCallUsed() ?? false;
7832
8119
  }
7833
8120
  include(context, includeChildrenRecursively) {
7834
- if (!this.parameterVariableValuesDeoptimized && !this.onlyFunctionCallUsed()) {
8121
+ if (!this.included)
8122
+ this.includeNode(context);
8123
+ if (!(this.parameterVariableValuesDeoptimized || this.onlyFunctionCallUsed())) {
7835
8124
  this.parameterVariableValuesDeoptimized = true;
7836
- this.deoptimizeParameterVariableValues();
8125
+ this.scope.reassignAllParameters();
7837
8126
  }
7838
- if (!this.deoptimized)
7839
- this.applyDeoptimizations();
7840
- this.included = true;
7841
8127
  const { brokenFlow } = context;
7842
8128
  context.brokenFlow = false;
7843
8129
  this.body.include(context, includeChildrenRecursively);
7844
8130
  context.brokenFlow = brokenFlow;
7845
8131
  }
7846
- includeCallArguments(context, parameters) {
7847
- this.scope.includeCallArguments(context, parameters);
7848
- }
7849
8132
  initialise() {
7850
8133
  super.initialise();
7851
8134
  if (this.body instanceof BlockStatement) {
@@ -7867,14 +8150,14 @@ class FunctionBase extends NodeBase {
7867
8150
  // so that the scope already knows all parameters and can detect conflicts
7868
8151
  // when parsing the body.
7869
8152
  const parameters = (this.params = params.map((parameter) => new (context.getNodeConstructor(parameter.type))(this, scope).parseNode(parameter)));
7870
- scope.addParameterVariables(parameters.map(parameter => parameter.declare('parameter', UNKNOWN_EXPRESSION)), parameters[parameters.length - 1] instanceof RestElement);
8153
+ scope.addParameterVariables(parameters.map(parameter => parameter.declare('parameter', EMPTY_PATH, UNKNOWN_EXPRESSION)), parameters[parameters.length - 1] instanceof RestElement);
7871
8154
  this.body = new (context.getNodeConstructor(body.type))(this, bodyScope).parseNode(body);
7872
8155
  return super.parseNode(esTreeNode);
7873
8156
  }
7874
- addArgumentToBeDeoptimized(_argument) { }
7875
- applyDeoptimizations() { }
7876
8157
  }
7877
8158
  FunctionBase.prototype.preventChildBlockScope = true;
8159
+ FunctionBase.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
8160
+ FunctionBase.prototype.applyDeoptimizations = doNotDeoptimize;
7878
8161
 
7879
8162
  class FunctionNode extends FunctionBase {
7880
8163
  constructor() {
@@ -7886,30 +8169,31 @@ class FunctionNode extends FunctionBase {
7886
8169
  this.constructedEntity = new ObjectEntity(Object.create(null), OBJECT_PROTOTYPE);
7887
8170
  // This makes sure that all deoptimizations of "this" are applied to the
7888
8171
  // constructed entity.
7889
- this.scope.thisVariable.addEntityToBeDeoptimized(this.constructedEntity);
8172
+ this.scope.thisVariable.addArgumentValue(this.constructedEntity);
7890
8173
  }
7891
8174
  deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
7892
8175
  super.deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker);
7893
8176
  if (interaction.type === INTERACTION_CALLED && path.length === 0 && interaction.args[0]) {
7894
8177
  // args[0] is the "this" argument
7895
- this.scope.thisVariable.addEntityToBeDeoptimized(interaction.args[0]);
8178
+ this.scope.thisVariable.addArgumentValue(interaction.args[0]);
7896
8179
  }
7897
8180
  }
7898
8181
  hasEffects(context) {
7899
- if (!this.deoptimized)
7900
- this.applyDeoptimizations();
7901
8182
  if (this.annotationNoSideEffects) {
7902
8183
  return false;
7903
8184
  }
7904
8185
  return !!this.id?.hasEffects(context);
7905
8186
  }
7906
8187
  hasEffectsOnInteractionAtPath(path, interaction, context) {
7907
- if (super.hasEffectsOnInteractionAtPath(path, interaction, context))
7908
- return true;
7909
- if (this.annotationNoSideEffects) {
8188
+ if (this.annotationNoSideEffects &&
8189
+ path.length === 0 &&
8190
+ interaction.type === INTERACTION_CALLED) {
7910
8191
  return false;
7911
8192
  }
7912
- if (interaction.type === INTERACTION_CALLED) {
8193
+ if (super.hasEffectsOnInteractionAtPath(path, interaction, context)) {
8194
+ return true;
8195
+ }
8196
+ if (path.length === 0 && interaction.type === INTERACTION_CALLED) {
7913
8197
  const thisInit = context.replacedVariableInits.get(this.scope.thisVariable);
7914
8198
  context.replacedVariableInits.set(this.scope.thisVariable, interaction.withNew ? this.constructedEntity : UNKNOWN_EXPRESSION);
7915
8199
  const { brokenFlow, ignore, replacedVariableInits } = context;
@@ -7920,8 +8204,10 @@ class FunctionNode extends FunctionBase {
7920
8204
  returnYield: true,
7921
8205
  this: interaction.withNew
7922
8206
  };
7923
- if (this.body.hasEffects(context))
8207
+ if (this.body.hasEffects(context)) {
8208
+ this.hasCachedEffects = true;
7924
8209
  return true;
8210
+ }
7925
8211
  context.brokenFlow = brokenFlow;
7926
8212
  if (thisInit) {
7927
8213
  replacedVariableInits.set(this.scope.thisVariable, thisInit);
@@ -7935,7 +8221,7 @@ class FunctionNode extends FunctionBase {
7935
8221
  }
7936
8222
  include(context, includeChildrenRecursively) {
7937
8223
  super.include(context, includeChildrenRecursively);
7938
- this.id?.include();
8224
+ this.id?.include(context);
7939
8225
  const hasArguments = this.scope.argumentsVariable.included;
7940
8226
  for (const parameter of this.params) {
7941
8227
  if (!(parameter instanceof Identifier) || hasArguments) {
@@ -7943,12 +8229,18 @@ class FunctionNode extends FunctionBase {
7943
8229
  }
7944
8230
  }
7945
8231
  }
8232
+ includeNode(context) {
8233
+ this.included = true;
8234
+ const hasArguments = this.scope.argumentsVariable.included;
8235
+ for (const parameter of this.params) {
8236
+ if (!(parameter instanceof Identifier) || hasArguments) {
8237
+ parameter.includePath(UNKNOWN_PATH, context);
8238
+ }
8239
+ }
8240
+ }
7946
8241
  initialise() {
7947
8242
  super.initialise();
7948
- this.id?.declare('function', this);
7949
- }
7950
- addArgumentToBeDeoptimized(argument) {
7951
- this.scope.argumentsVariable.addArgumentToBeDeoptimized(argument);
8243
+ this.id?.declare('function', EMPTY_PATH, this);
7952
8244
  }
7953
8245
  getObjectEntity() {
7954
8246
  if (this.objectEntity !== null) {
@@ -7998,11 +8290,16 @@ function getFunctionIdInsertPosition(code, start) {
7998
8290
  }
7999
8291
  class ExportDefaultDeclaration extends NodeBase {
8000
8292
  include(context, includeChildrenRecursively) {
8001
- super.include(context, includeChildrenRecursively);
8293
+ this.included = true;
8294
+ this.declaration.include(context, includeChildrenRecursively);
8002
8295
  if (includeChildrenRecursively) {
8003
- this.scope.context.includeVariableInModule(this.variable);
8296
+ this.scope.context.includeVariableInModule(this.variable, UNKNOWN_PATH, context);
8004
8297
  }
8005
8298
  }
8299
+ includePath(path, context) {
8300
+ this.included = true;
8301
+ this.declaration.includePath(path, context);
8302
+ }
8006
8303
  initialise() {
8007
8304
  super.initialise();
8008
8305
  const declaration = this.declaration;
@@ -8047,7 +8344,6 @@ class ExportDefaultDeclaration extends NodeBase {
8047
8344
  }
8048
8345
  this.declaration.render(code, options);
8049
8346
  }
8050
- applyDeoptimizations() { }
8051
8347
  renderNamedDeclaration(code, declarationStart, idInsertPosition, options) {
8052
8348
  const { exportNamesByVariable, format, snippets: { getPropertyAccess } } = options;
8053
8349
  const name = this.variable.getName(getPropertyAccess);
@@ -8078,6 +8374,8 @@ class ExportDefaultDeclaration extends NodeBase {
8078
8374
  }
8079
8375
  }
8080
8376
  ExportDefaultDeclaration.prototype.needsBoundaries = true;
8377
+ ExportDefaultDeclaration.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
8378
+ ExportDefaultDeclaration.prototype.applyDeoptimizations = doNotDeoptimize;
8081
8379
 
8082
8380
  const needsEscapeRegEx = /[\n\r'\\\u2028\u2029]/;
8083
8381
  const quoteNewlineRegEx = /([\n\r'\u2028\u2029])/g;
@@ -8347,6 +8645,7 @@ class Literal extends NodeBase {
8347
8645
  }
8348
8646
  }
8349
8647
  }
8648
+ Literal.prototype.includeNode = onlyIncludeSelf;
8350
8649
 
8351
8650
  function getChainElementLiteralValueAtPath(element, object, path, recursionTracker, origin) {
8352
8651
  if ('getLiteralValueAtPathAsChainElement' in object) {
@@ -8362,8 +8661,6 @@ function getChainElementLiteralValueAtPath(element, object, path, recursionTrack
8362
8661
  return element.getLiteralValueAtPath(path, recursionTracker, origin);
8363
8662
  }
8364
8663
 
8365
- // To avoid infinite recursions
8366
- const MAX_PATH_DEPTH = 7;
8367
8664
  function getResolvablePropertyKey(memberExpression) {
8368
8665
  return memberExpression.computed
8369
8666
  ? getResolvableComputedPropertyKey(memberExpression.property)
@@ -8462,18 +8759,27 @@ class MemberExpression extends NodeBase {
8462
8759
  }
8463
8760
  else if (!this.isUndefined) {
8464
8761
  if (path.length < MAX_PATH_DEPTH) {
8465
- this.object.deoptimizeArgumentsOnInteractionAtPath(interaction, [this.getPropertyKey(), ...path], recursionTracker);
8762
+ this.object.deoptimizeArgumentsOnInteractionAtPath(interaction, this.propertyKey === UnknownKey ? UNKNOWN_PATH : [this.propertyKey, ...path], recursionTracker);
8466
8763
  }
8467
8764
  else {
8468
8765
  deoptimizeInteraction(interaction);
8469
8766
  }
8470
8767
  }
8471
8768
  }
8769
+ deoptimizeAssignment(destructuredInitPath, init) {
8770
+ this.deoptimizePath(EMPTY_PATH);
8771
+ init.deoptimizePath([...destructuredInitPath, UnknownKey]);
8772
+ }
8472
8773
  deoptimizeCache() {
8774
+ if (this.propertyKey === this.dynamicPropertyKey)
8775
+ return;
8473
8776
  const { expressionsToBeDeoptimized, object } = this;
8474
8777
  this.expressionsToBeDeoptimized = parseAst_js.EMPTY_ARRAY;
8475
- this.propertyKey = UnknownKey;
8778
+ this.dynamicPropertyKey = this.propertyKey;
8476
8779
  object.deoptimizePath(UNKNOWN_PATH);
8780
+ if (this.included) {
8781
+ object.includePath(UNKNOWN_PATH, createInclusionContext());
8782
+ }
8477
8783
  for (const expression of expressionsToBeDeoptimized) {
8478
8784
  expression.deoptimizeCache();
8479
8785
  }
@@ -8484,11 +8790,13 @@ class MemberExpression extends NodeBase {
8484
8790
  if (this.variable) {
8485
8791
  this.variable.deoptimizePath(path);
8486
8792
  }
8487
- else if (!this.isUndefined && path.length < MAX_PATH_DEPTH) {
8488
- const propertyKey = this.getPropertyKey();
8793
+ else if (!this.isUndefined) {
8794
+ const { propertyKey } = this;
8489
8795
  this.object.deoptimizePath([
8490
8796
  propertyKey === UnknownKey ? UnknownNonAccessorKey : propertyKey,
8491
- ...path
8797
+ ...(path.length < MAX_PATH_DEPTH
8798
+ ? path
8799
+ : [...path.slice(0, MAX_PATH_DEPTH), UnknownKey])
8492
8800
  ]);
8493
8801
  }
8494
8802
  }
@@ -8499,9 +8807,11 @@ class MemberExpression extends NodeBase {
8499
8807
  if (this.isUndefined) {
8500
8808
  return undefined;
8501
8809
  }
8502
- if (this.propertyKey !== UnknownKey && path.length < MAX_PATH_DEPTH) {
8503
- this.expressionsToBeDeoptimized.push(origin);
8504
- return this.object.getLiteralValueAtPath([this.getPropertyKey(), ...path], recursionTracker, origin);
8810
+ const propertyKey = this.getDynamicPropertyKey();
8811
+ if (propertyKey !== UnknownKey && path.length < MAX_PATH_DEPTH) {
8812
+ if (propertyKey !== this.propertyKey)
8813
+ this.expressionsToBeDeoptimized.push(origin);
8814
+ return this.object.getLiteralValueAtPath([propertyKey, ...path], recursionTracker, origin);
8505
8815
  }
8506
8816
  return UnknownValue;
8507
8817
  }
@@ -8521,9 +8831,11 @@ class MemberExpression extends NodeBase {
8521
8831
  if (this.isUndefined) {
8522
8832
  return [UNDEFINED_EXPRESSION, false];
8523
8833
  }
8524
- if (this.propertyKey !== UnknownKey && path.length < MAX_PATH_DEPTH) {
8525
- this.expressionsToBeDeoptimized.push(origin);
8526
- return this.object.getReturnExpressionWhenCalledAtPath([this.getPropertyKey(), ...path], interaction, recursionTracker, origin);
8834
+ const propertyKey = this.getDynamicPropertyKey();
8835
+ if (propertyKey !== UnknownKey && path.length < MAX_PATH_DEPTH) {
8836
+ if (propertyKey !== this.propertyKey)
8837
+ this.expressionsToBeDeoptimized.push(origin);
8838
+ return this.object.getReturnExpressionWhenCalledAtPath([propertyKey, ...path], interaction, recursionTracker, origin);
8527
8839
  }
8528
8840
  return UNKNOWN_RETURN_EXPRESSION;
8529
8841
  }
@@ -8569,14 +8881,45 @@ class MemberExpression extends NodeBase {
8569
8881
  return true;
8570
8882
  }
8571
8883
  if (path.length < MAX_PATH_DEPTH) {
8572
- return this.object.hasEffectsOnInteractionAtPath([this.getPropertyKey(), ...path], interaction, context);
8884
+ return this.object.hasEffectsOnInteractionAtPath([this.getDynamicPropertyKey(), ...path], interaction, context);
8573
8885
  }
8574
8886
  return true;
8575
8887
  }
8888
+ hasEffectsWhenDestructuring(context, destructuredInitPath, init) {
8889
+ return (destructuredInitPath.length > 0 &&
8890
+ init.hasEffectsOnInteractionAtPath(destructuredInitPath, NODE_INTERACTION_UNKNOWN_ACCESS, context));
8891
+ }
8576
8892
  include(context, includeChildrenRecursively) {
8893
+ if (!this.included)
8894
+ this.includeNode(context);
8895
+ this.object.include(context, includeChildrenRecursively);
8896
+ this.property.include(context, includeChildrenRecursively);
8897
+ }
8898
+ includeNode(context) {
8899
+ this.included = true;
8577
8900
  if (!this.deoptimized)
8578
8901
  this.applyDeoptimizations();
8579
- this.includeProperties(context, includeChildrenRecursively);
8902
+ if (this.variable) {
8903
+ this.scope.context.includeVariableInModule(this.variable, EMPTY_PATH, context);
8904
+ }
8905
+ else if (!this.isUndefined) {
8906
+ this.object.includePath([this.propertyKey], context);
8907
+ }
8908
+ }
8909
+ includePath(path, context) {
8910
+ if (!this.included)
8911
+ this.includeNode(context);
8912
+ if (this.variable) {
8913
+ this.variable?.includePath(path, context);
8914
+ }
8915
+ else if (!this.isUndefined) {
8916
+ this.object.includePath([
8917
+ this.propertyKey,
8918
+ ...(path.length < MAX_PATH_DEPTH
8919
+ ? path
8920
+ : [...path.slice(0, MAX_PATH_DEPTH), UnknownKey])
8921
+ ], context);
8922
+ }
8580
8923
  }
8581
8924
  includeAsAssignmentTarget(context, includeChildrenRecursively, deoptimizeAccess) {
8582
8925
  if (!this.assignmentDeoptimized)
@@ -8585,20 +8928,34 @@ class MemberExpression extends NodeBase {
8585
8928
  this.include(context, includeChildrenRecursively);
8586
8929
  }
8587
8930
  else {
8588
- this.includeProperties(context, includeChildrenRecursively);
8931
+ if (!this.included)
8932
+ this.includeNode(context);
8933
+ this.object.include(context, includeChildrenRecursively);
8934
+ this.property.include(context, includeChildrenRecursively);
8589
8935
  }
8590
8936
  }
8591
- includeCallArguments(context, parameters) {
8937
+ includeCallArguments(context, interaction) {
8592
8938
  if (this.variable) {
8593
- this.variable.includeCallArguments(context, parameters);
8939
+ this.variable.includeCallArguments(context, interaction);
8594
8940
  }
8595
8941
  else {
8596
- super.includeCallArguments(context, parameters);
8942
+ super.includeCallArguments(context, interaction);
8943
+ }
8944
+ }
8945
+ includeDestructuredIfNecessary(context, destructuredInitPath, init) {
8946
+ if ((this.included ||=
8947
+ destructuredInitPath.length > 0 &&
8948
+ !context.brokenFlow &&
8949
+ init.hasEffectsOnInteractionAtPath(destructuredInitPath, NODE_INTERACTION_UNKNOWN_ACCESS, createHasEffectsContext()))) {
8950
+ init.include(context, false);
8951
+ return true;
8597
8952
  }
8953
+ return false;
8598
8954
  }
8599
8955
  initialise() {
8600
8956
  super.initialise();
8601
- this.propertyKey = getResolvablePropertyKey(this);
8957
+ this.dynamicPropertyKey = getResolvablePropertyKey(this);
8958
+ this.propertyKey = this.dynamicPropertyKey === null ? UnknownKey : this.dynamicPropertyKey;
8602
8959
  this.accessInteraction = { args: [this.object], type: INTERACTION_ACCESSED };
8603
8960
  }
8604
8961
  render(code, options, { renderedParentType, isCalleeOfRenderedParent, renderedSurroundingElement } = parseAst_js.BLANK) {
@@ -8635,8 +8992,7 @@ class MemberExpression extends NodeBase {
8635
8992
  this.bound &&
8636
8993
  propertyReadSideEffects &&
8637
8994
  !(this.variable || this.isUndefined)) {
8638
- const propertyKey = this.getPropertyKey();
8639
- this.object.deoptimizeArgumentsOnInteractionAtPath(this.accessInteraction, [propertyKey], SHARED_RECURSION_TRACKER);
8995
+ this.object.deoptimizeArgumentsOnInteractionAtPath(this.accessInteraction, [this.propertyKey], SHARED_RECURSION_TRACKER);
8640
8996
  this.scope.context.requestTreeshakingPass();
8641
8997
  }
8642
8998
  if (this.variable) {
@@ -8653,7 +9009,7 @@ class MemberExpression extends NodeBase {
8653
9009
  this.bound &&
8654
9010
  propertyReadSideEffects &&
8655
9011
  !(this.variable || this.isUndefined)) {
8656
- this.object.deoptimizeArgumentsOnInteractionAtPath(this.assignmentInteraction, [this.getPropertyKey()], SHARED_RECURSION_TRACKER);
9012
+ this.object.deoptimizeArgumentsOnInteractionAtPath(this.assignmentInteraction, [this.propertyKey], SHARED_RECURSION_TRACKER);
8657
9013
  this.scope.context.requestTreeshakingPass();
8658
9014
  }
8659
9015
  }
@@ -8662,24 +9018,24 @@ class MemberExpression extends NodeBase {
8662
9018
  const variable = this.scope.findVariable(this.object.name);
8663
9019
  if (variable.isNamespace) {
8664
9020
  if (this.variable) {
8665
- this.scope.context.includeVariableInModule(this.variable);
9021
+ this.scope.context.includeVariableInModule(this.variable, UNKNOWN_PATH, createInclusionContext());
8666
9022
  }
8667
9023
  this.scope.context.log(parseAst_js.LOGLEVEL_WARN, parseAst_js.logIllegalImportReassignment(this.object.name, this.scope.context.module.id), this.start);
8668
9024
  }
8669
9025
  }
8670
9026
  }
8671
- getPropertyKey() {
8672
- if (this.propertyKey === null) {
8673
- this.propertyKey = UnknownKey;
9027
+ getDynamicPropertyKey() {
9028
+ if (this.dynamicPropertyKey === null) {
9029
+ this.dynamicPropertyKey = this.propertyKey;
8674
9030
  const value = this.property.getLiteralValueAtPath(EMPTY_PATH, SHARED_RECURSION_TRACKER, this);
8675
- return (this.propertyKey =
9031
+ return (this.dynamicPropertyKey =
8676
9032
  value === SymbolToStringTag
8677
9033
  ? value
8678
9034
  : typeof value === 'symbol'
8679
9035
  ? UnknownKey
8680
9036
  : String(value));
8681
9037
  }
8682
- return this.propertyKey;
9038
+ return this.dynamicPropertyKey;
8683
9039
  }
8684
9040
  hasAccessEffect(context) {
8685
9041
  const { propertyReadSideEffects } = this.scope.context.options
@@ -8687,17 +9043,7 @@ class MemberExpression extends NodeBase {
8687
9043
  return (!(this.variable || this.isUndefined) &&
8688
9044
  propertyReadSideEffects &&
8689
9045
  (propertyReadSideEffects === 'always' ||
8690
- this.object.hasEffectsOnInteractionAtPath([this.getPropertyKey()], this.accessInteraction, context)));
8691
- }
8692
- includeProperties(context, includeChildrenRecursively) {
8693
- if (!this.included) {
8694
- this.included = true;
8695
- if (this.variable) {
8696
- this.scope.context.includeVariableInModule(this.variable);
8697
- }
8698
- }
8699
- this.object.include(context, includeChildrenRecursively);
8700
- this.property.include(context, includeChildrenRecursively);
9046
+ this.object.hasEffectsOnInteractionAtPath([this.getDynamicPropertyKey()], this.accessInteraction, context)));
8701
9047
  }
8702
9048
  }
8703
9049
  function resolveNamespaceVariables(baseVariable, path, astContext) {
@@ -8741,18 +9087,20 @@ class MetaProperty extends NodeBase {
8741
9087
  return path.length > 1 || type !== INTERACTION_ACCESSED;
8742
9088
  }
8743
9089
  include() {
8744
- if (!this.included) {
8745
- this.included = true;
8746
- if (this.meta.name === IMPORT) {
8747
- this.scope.context.addImportMeta(this);
8748
- const parent = this.parent;
8749
- const metaProperty = (this.metaProperty =
8750
- parent instanceof MemberExpression && typeof parent.propertyKey === 'string'
8751
- ? parent.propertyKey
8752
- : null);
8753
- if (metaProperty?.startsWith(FILE_PREFIX)) {
8754
- this.referenceId = metaProperty.slice(FILE_PREFIX.length);
8755
- }
9090
+ if (!this.included)
9091
+ this.includeNode();
9092
+ }
9093
+ includeNode() {
9094
+ this.included = true;
9095
+ if (this.meta.name === IMPORT) {
9096
+ this.scope.context.addImportMeta(this);
9097
+ const parent = this.parent;
9098
+ const metaProperty = (this.metaProperty =
9099
+ parent instanceof MemberExpression && typeof parent.propertyKey === 'string'
9100
+ ? parent.propertyKey
9101
+ : null);
9102
+ if (metaProperty?.startsWith(FILE_PREFIX)) {
9103
+ this.referenceId = metaProperty.slice(FILE_PREFIX.length);
8756
9104
  }
8757
9105
  }
8758
9106
  }
@@ -8859,7 +9207,7 @@ class UndefinedVariable extends Variable {
8859
9207
 
8860
9208
  class ExportDefaultVariable extends LocalVariable {
8861
9209
  constructor(name, exportDefaultDeclaration, context) {
8862
- super(name, exportDefaultDeclaration, exportDefaultDeclaration.declaration, context, 'other');
9210
+ super(name, exportDefaultDeclaration, exportDefaultDeclaration.declaration, EMPTY_PATH, context, 'other');
8863
9211
  this.hasId = false;
8864
9212
  this.originalId = null;
8865
9213
  this.originalVariable = null;
@@ -9008,8 +9356,8 @@ class NamespaceVariable extends Variable {
9008
9356
  return (!memberVariable ||
9009
9357
  memberVariable.hasEffectsOnInteractionAtPath(path.slice(1), interaction, context));
9010
9358
  }
9011
- include() {
9012
- super.include();
9359
+ includePath(path, context) {
9360
+ super.includePath(path, context);
9013
9361
  this.context.includeAllExports();
9014
9362
  }
9015
9363
  prepare(accessedGlobalsByScope) {
@@ -9102,9 +9450,9 @@ class SyntheticNamedExportVariable extends Variable {
9102
9450
  getName(getPropertyAccess) {
9103
9451
  return `${this.syntheticNamespace.getName(getPropertyAccess)}${getPropertyAccess(this.name)}`;
9104
9452
  }
9105
- include() {
9106
- super.include();
9107
- this.context.includeVariableInModule(this.syntheticNamespace);
9453
+ includePath(path, context) {
9454
+ super.includePath(path, context);
9455
+ this.context.includeVariableInModule(this.syntheticNamespace, path, context);
9108
9456
  }
9109
9457
  setRenderNames(baseName, name) {
9110
9458
  super.setRenderNames(baseName, name);
@@ -12280,21 +12628,37 @@ class ArrayPattern extends NodeBase {
12280
12628
  element?.addExportedVariables(variables, exportNamesByVariable);
12281
12629
  }
12282
12630
  }
12283
- declare(kind) {
12631
+ declare(kind, destructuredInitPath, init) {
12284
12632
  const variables = [];
12633
+ const includedPatternPath = getIncludedPatternPath(destructuredInitPath);
12285
12634
  for (const element of this.elements) {
12286
12635
  if (element !== null) {
12287
- variables.push(...element.declare(kind, UNKNOWN_EXPRESSION));
12636
+ variables.push(...element.declare(kind, includedPatternPath, init));
12288
12637
  }
12289
12638
  }
12290
12639
  return variables;
12291
12640
  }
12641
+ deoptimizeAssignment(destructuredInitPath, init) {
12642
+ const includedPatternPath = getIncludedPatternPath(destructuredInitPath);
12643
+ for (const element of this.elements) {
12644
+ element?.deoptimizeAssignment(includedPatternPath, init);
12645
+ }
12646
+ }
12292
12647
  // Patterns can only be deoptimized at the empty path at the moment
12293
12648
  deoptimizePath() {
12294
12649
  for (const element of this.elements) {
12295
12650
  element?.deoptimizePath(EMPTY_PATH);
12296
12651
  }
12297
12652
  }
12653
+ hasEffectsWhenDestructuring(context, destructuredInitPath, init) {
12654
+ const includedPatternPath = getIncludedPatternPath(destructuredInitPath);
12655
+ for (const element of this.elements) {
12656
+ if (element?.hasEffectsWhenDestructuring(context, includedPatternPath, init)) {
12657
+ return true;
12658
+ }
12659
+ }
12660
+ return false;
12661
+ }
12298
12662
  // Patterns are only checked at the empty path at the moment
12299
12663
  hasEffectsOnInteractionAtPath(_path, interaction, context) {
12300
12664
  for (const element of this.elements) {
@@ -12303,12 +12667,38 @@ class ArrayPattern extends NodeBase {
12303
12667
  }
12304
12668
  return false;
12305
12669
  }
12670
+ includeDestructuredIfNecessary(context, destructuredInitPath, init) {
12671
+ let included = false;
12672
+ const includedPatternPath = getIncludedPatternPath(destructuredInitPath);
12673
+ for (const element of this.elements) {
12674
+ if (element) {
12675
+ element.included ||= included;
12676
+ included =
12677
+ element.includeDestructuredIfNecessary(context, includedPatternPath, init) || included;
12678
+ }
12679
+ }
12680
+ if (included) {
12681
+ // This is necessary so that if any pattern element is included, all are
12682
+ // included for proper deconflicting
12683
+ for (const element of this.elements) {
12684
+ if (element && !element.included) {
12685
+ element.included = true;
12686
+ element.includeDestructuredIfNecessary(context, includedPatternPath, init);
12687
+ }
12688
+ }
12689
+ }
12690
+ return (this.included ||= included);
12691
+ }
12306
12692
  markDeclarationReached() {
12307
12693
  for (const element of this.elements) {
12308
12694
  element?.markDeclarationReached();
12309
12695
  }
12310
12696
  }
12311
12697
  }
12698
+ ArrayPattern.prototype.includeNode = onlyIncludeSelf;
12699
+ const getIncludedPatternPath = (destructuredInitPath) => destructuredInitPath.at(-1) === UnknownKey
12700
+ ? destructuredInitPath
12701
+ : [...destructuredInitPath, UnknownInteger];
12312
12702
 
12313
12703
  class ArrowFunctionExpression extends FunctionBase {
12314
12704
  constructor() {
@@ -12325,17 +12715,17 @@ class ArrowFunctionExpression extends FunctionBase {
12325
12715
  this.scope = new ReturnValueScope(parentScope, false);
12326
12716
  }
12327
12717
  hasEffects() {
12328
- if (!this.deoptimized)
12329
- this.applyDeoptimizations();
12330
12718
  return false;
12331
12719
  }
12332
12720
  hasEffectsOnInteractionAtPath(path, interaction, context) {
12721
+ if (this.annotationNoSideEffects &&
12722
+ path.length === 0 &&
12723
+ interaction.type === INTERACTION_CALLED) {
12724
+ return false;
12725
+ }
12333
12726
  if (super.hasEffectsOnInteractionAtPath(path, interaction, context)) {
12334
12727
  return true;
12335
12728
  }
12336
- if (this.annotationNoSideEffects) {
12337
- return false;
12338
- }
12339
12729
  if (interaction.type === INTERACTION_CALLED) {
12340
12730
  const { ignore, brokenFlow } = context;
12341
12731
  context.ignore = {
@@ -12365,6 +12755,15 @@ class ArrowFunctionExpression extends FunctionBase {
12365
12755
  }
12366
12756
  }
12367
12757
  }
12758
+ includeNode(context) {
12759
+ this.included = true;
12760
+ this.body.includePath(UNKNOWN_PATH, context);
12761
+ for (const parameter of this.params) {
12762
+ if (!(parameter instanceof Identifier)) {
12763
+ parameter.includePath(UNKNOWN_PATH, context);
12764
+ }
12765
+ }
12766
+ }
12368
12767
  getObjectEntity() {
12369
12768
  if (this.objectEntity !== null) {
12370
12769
  return this.objectEntity;
@@ -12384,13 +12783,18 @@ class ObjectPattern extends NodeBase {
12384
12783
  }
12385
12784
  }
12386
12785
  }
12387
- declare(kind, init) {
12786
+ declare(kind, destructuredInitPath, init) {
12388
12787
  const variables = [];
12389
12788
  for (const property of this.properties) {
12390
- variables.push(...property.declare(kind, init));
12789
+ variables.push(...property.declare(kind, destructuredInitPath, init));
12391
12790
  }
12392
12791
  return variables;
12393
12792
  }
12793
+ deoptimizeAssignment(destructuredInitPath, init) {
12794
+ for (const property of this.properties) {
12795
+ property.deoptimizeAssignment(destructuredInitPath, init);
12796
+ }
12797
+ }
12394
12798
  deoptimizePath(path) {
12395
12799
  if (path.length === 0) {
12396
12800
  for (const property of this.properties) {
@@ -12408,12 +12812,46 @@ class ObjectPattern extends NodeBase {
12408
12812
  }
12409
12813
  return false;
12410
12814
  }
12815
+ hasEffectsWhenDestructuring(context, destructuredInitPath, init) {
12816
+ for (const property of this.properties) {
12817
+ if (property.hasEffectsWhenDestructuring(context, destructuredInitPath, init))
12818
+ return true;
12819
+ }
12820
+ return false;
12821
+ }
12822
+ includeDestructuredIfNecessary(context, destructuredInitPath, init) {
12823
+ let included = false;
12824
+ for (const property of this.properties) {
12825
+ included =
12826
+ property.includeDestructuredIfNecessary(context, destructuredInitPath, init) || included;
12827
+ }
12828
+ return (this.included ||= included);
12829
+ }
12411
12830
  markDeclarationReached() {
12412
12831
  for (const property of this.properties) {
12413
12832
  property.markDeclarationReached();
12414
12833
  }
12415
12834
  }
12835
+ render(code, options) {
12836
+ if (this.properties.length > 0) {
12837
+ const separatedNodes = getCommaSeparatedNodesWithBoundaries(this.properties, code, this.start + 1, this.end - 1);
12838
+ let lastSeparatorPos = null;
12839
+ for (const { node, separator, start, end } of separatedNodes) {
12840
+ if (!node.included) {
12841
+ treeshakeNode(node, code, start, end);
12842
+ continue;
12843
+ }
12844
+ lastSeparatorPos = separator;
12845
+ node.render(code, options);
12846
+ }
12847
+ if (lastSeparatorPos) {
12848
+ code.remove(lastSeparatorPos, this.end - 1);
12849
+ }
12850
+ }
12851
+ }
12416
12852
  }
12853
+ ObjectPattern.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
12854
+ ObjectPattern.prototype.applyDeoptimizations = doNotDeoptimize;
12417
12855
 
12418
12856
  class AssignmentExpression extends NodeBase {
12419
12857
  hasEffects(context) {
@@ -12422,7 +12860,9 @@ class AssignmentExpression extends NodeBase {
12422
12860
  this.applyDeoptimizations();
12423
12861
  // MemberExpressions do not access the property before assignments if the
12424
12862
  // operator is '='.
12425
- return (right.hasEffects(context) || left.hasEffectsAsAssignmentTarget(context, operator !== '='));
12863
+ return (right.hasEffects(context) ||
12864
+ left.hasEffectsAsAssignmentTarget(context, operator !== '=') ||
12865
+ this.left.hasEffectsWhenDestructuring?.(context, EMPTY_PATH, right));
12426
12866
  }
12427
12867
  hasEffectsOnInteractionAtPath(path, interaction, context) {
12428
12868
  return this.right.hasEffectsOnInteractionAtPath(path, interaction, context);
@@ -12431,15 +12871,24 @@ class AssignmentExpression extends NodeBase {
12431
12871
  const { deoptimized, left, right, operator } = this;
12432
12872
  if (!deoptimized)
12433
12873
  this.applyDeoptimizations();
12434
- this.included = true;
12874
+ if (!this.included)
12875
+ this.includeNode(context);
12876
+ const hasEffectsContext = createHasEffectsContext();
12435
12877
  if (includeChildrenRecursively ||
12436
12878
  operator !== '=' ||
12437
12879
  left.included ||
12438
- left.hasEffectsAsAssignmentTarget(createHasEffectsContext(), false)) {
12880
+ left.hasEffectsAsAssignmentTarget(hasEffectsContext, false) ||
12881
+ left.hasEffectsWhenDestructuring?.(hasEffectsContext, EMPTY_PATH, right)) {
12439
12882
  left.includeAsAssignmentTarget(context, includeChildrenRecursively, operator !== '=');
12440
12883
  }
12441
12884
  right.include(context, includeChildrenRecursively);
12442
12885
  }
12886
+ includeNode(context) {
12887
+ this.included = true;
12888
+ if (!this.deoptimized)
12889
+ this.applyDeoptimizations();
12890
+ this.right.includePath(UNKNOWN_PATH, context);
12891
+ }
12443
12892
  initialise() {
12444
12893
  super.initialise();
12445
12894
  if (this.left instanceof Identifier) {
@@ -12500,8 +12949,7 @@ class AssignmentExpression extends NodeBase {
12500
12949
  }
12501
12950
  applyDeoptimizations() {
12502
12951
  this.deoptimized = true;
12503
- this.left.deoptimizePath(EMPTY_PATH);
12504
- this.right.deoptimizePath(UNKNOWN_PATH);
12952
+ this.left.deoptimizeAssignment(EMPTY_PATH, this.right);
12505
12953
  this.scope.context.requestTreeshakingPass();
12506
12954
  }
12507
12955
  }
@@ -12510,8 +12958,11 @@ class AssignmentPattern extends NodeBase {
12510
12958
  addExportedVariables(variables, exportNamesByVariable) {
12511
12959
  this.left.addExportedVariables(variables, exportNamesByVariable);
12512
12960
  }
12513
- declare(kind, init) {
12514
- return this.left.declare(kind, init);
12961
+ declare(kind, destructuredInitPath, init) {
12962
+ return this.left.declare(kind, destructuredInitPath, init);
12963
+ }
12964
+ deoptimizeAssignment(destructuredInitPath, init) {
12965
+ this.left.deoptimizeAssignment(destructuredInitPath, init);
12515
12966
  }
12516
12967
  deoptimizePath(path) {
12517
12968
  if (path.length === 0) {
@@ -12521,6 +12972,29 @@ class AssignmentPattern extends NodeBase {
12521
12972
  hasEffectsOnInteractionAtPath(path, interaction, context) {
12522
12973
  return (path.length > 0 || this.left.hasEffectsOnInteractionAtPath(EMPTY_PATH, interaction, context));
12523
12974
  }
12975
+ hasEffectsWhenDestructuring(context, destructuredInitPath, init) {
12976
+ return this.left.hasEffectsWhenDestructuring(context, destructuredInitPath, init);
12977
+ }
12978
+ includeDestructuredIfNecessary(context, destructuredInitPath, init) {
12979
+ let included = this.left.includeDestructuredIfNecessary(context, destructuredInitPath, init) ||
12980
+ this.included;
12981
+ if ((included ||= this.right.shouldBeIncluded(context))) {
12982
+ this.right.include(context, false);
12983
+ if (!this.left.included) {
12984
+ this.left.included = true;
12985
+ // Unfortunately, we need to include the left side again now, so that
12986
+ // any declared variables are properly included.
12987
+ this.left.includeDestructuredIfNecessary(context, destructuredInitPath, init);
12988
+ }
12989
+ }
12990
+ return (this.included = included);
12991
+ }
12992
+ includeNode(context) {
12993
+ this.included = true;
12994
+ if (!this.deoptimized)
12995
+ this.applyDeoptimizations();
12996
+ this.right.includePath(UNKNOWN_PATH, context);
12997
+ }
12524
12998
  markDeclarationReached() {
12525
12999
  this.left.markDeclarationReached();
12526
13000
  }
@@ -12543,22 +13017,34 @@ class AwaitExpression extends NodeBase {
12543
13017
  return true;
12544
13018
  }
12545
13019
  include(context, includeChildrenRecursively) {
13020
+ if (!this.included)
13021
+ this.includeNode(context);
13022
+ this.argument.include(context, includeChildrenRecursively);
13023
+ }
13024
+ includeNode(context) {
13025
+ this.included = true;
12546
13026
  if (!this.deoptimized)
12547
13027
  this.applyDeoptimizations();
12548
- if (!this.included) {
12549
- this.included = true;
12550
- checkTopLevelAwait: if (!this.scope.context.usesTopLevelAwait) {
12551
- let parent = this.parent;
12552
- do {
12553
- if (parent instanceof FunctionNode || parent instanceof ArrowFunctionExpression)
12554
- break checkTopLevelAwait;
12555
- } while ((parent = parent.parent));
12556
- this.scope.context.usesTopLevelAwait = true;
12557
- }
13028
+ checkTopLevelAwait: if (!this.scope.context.usesTopLevelAwait) {
13029
+ let parent = this.parent;
13030
+ do {
13031
+ if (parent instanceof FunctionNode || parent instanceof ArrowFunctionExpression)
13032
+ break checkTopLevelAwait;
13033
+ } while ((parent = parent.parent));
13034
+ this.scope.context.usesTopLevelAwait = true;
12558
13035
  }
12559
- this.argument.include(context, includeChildrenRecursively);
13036
+ // Thenables need to be included
13037
+ this.argument.includePath(THEN_PATH, context);
13038
+ }
13039
+ includePath(path, context) {
13040
+ if (!this.deoptimized)
13041
+ this.applyDeoptimizations();
13042
+ if (!this.included)
13043
+ this.includeNode(context);
13044
+ this.argument.includePath(path, context);
12560
13045
  }
12561
13046
  }
13047
+ const THEN_PATH = ['then'];
12562
13048
 
12563
13049
  const binaryOperators = {
12564
13050
  '!=': (left, right) => left != right,
@@ -12614,6 +13100,12 @@ class BinaryExpression extends NodeBase {
12614
13100
  hasEffectsOnInteractionAtPath(path, { type }) {
12615
13101
  return type !== INTERACTION_ACCESSED || path.length > 1;
12616
13102
  }
13103
+ includeNode(context) {
13104
+ this.included = true;
13105
+ if (this.operator === 'in') {
13106
+ this.right.includePath(UNKNOWN_PATH, context);
13107
+ }
13108
+ }
12617
13109
  removeAnnotations(code) {
12618
13110
  this.left.removeAnnotations(code);
12619
13111
  }
@@ -12622,6 +13114,7 @@ class BinaryExpression extends NodeBase {
12622
13114
  this.right.render(code, options);
12623
13115
  }
12624
13116
  }
13117
+ BinaryExpression.prototype.applyDeoptimizations = doNotDeoptimize;
12625
13118
 
12626
13119
  class BreakStatement extends NodeBase {
12627
13120
  hasEffects(context) {
@@ -12641,7 +13134,7 @@ class BreakStatement extends NodeBase {
12641
13134
  include(context) {
12642
13135
  this.included = true;
12643
13136
  if (this.label) {
12644
- this.label.include();
13137
+ this.label.include(context);
12645
13138
  context.includedLabels.add(this.label.name);
12646
13139
  }
12647
13140
  else {
@@ -12650,6 +13143,8 @@ class BreakStatement extends NodeBase {
12650
13143
  context.brokenFlow = true;
12651
13144
  }
12652
13145
  }
13146
+ BreakStatement.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
13147
+ BreakStatement.prototype.applyDeoptimizations = doNotDeoptimize;
12653
13148
 
12654
13149
  function renderCallArguments(code, options, node) {
12655
13150
  if (node.arguments.length > 0) {
@@ -12836,10 +13331,14 @@ class CallExpression extends CallExpressionBase {
12836
13331
  this.callee.hasEffectsOnInteractionAtPath(EMPTY_PATH, this.interaction, context)));
12837
13332
  }
12838
13333
  include(context, includeChildrenRecursively) {
12839
- if (!this.deoptimized)
12840
- this.applyDeoptimizations();
13334
+ if (!this.included)
13335
+ this.includeNode(context);
12841
13336
  if (includeChildrenRecursively) {
12842
- super.include(context, includeChildrenRecursively);
13337
+ this.callee.include(context, true);
13338
+ for (const argument of this.arguments) {
13339
+ argument.includePath(UNKNOWN_PATH, context);
13340
+ argument.include(context, true);
13341
+ }
12843
13342
  if (includeChildrenRecursively === INCLUDE_PARAMETERS &&
12844
13343
  this.callee instanceof Identifier &&
12845
13344
  this.callee.variable) {
@@ -12847,10 +13346,24 @@ class CallExpression extends CallExpressionBase {
12847
13346
  }
12848
13347
  }
12849
13348
  else {
12850
- this.included = true;
12851
- this.callee.include(context, false);
13349
+ // If the callee is a member expression and does not have a variable, its
13350
+ // object will already be included via the first argument of the
13351
+ // interaction in includeCallArguments. Including it again can lead to
13352
+ // severe performance problems.
13353
+ if (this.callee instanceof MemberExpression && !this.callee.variable) {
13354
+ this.callee.property.include(context, false);
13355
+ }
13356
+ else {
13357
+ this.callee.include(context, false);
13358
+ }
13359
+ this.callee.includeCallArguments(context, this.interaction);
12852
13360
  }
12853
- this.callee.includeCallArguments(context, this.arguments);
13361
+ }
13362
+ includeNode(context) {
13363
+ this.included = true;
13364
+ if (!this.deoptimized)
13365
+ this.applyDeoptimizations();
13366
+ this.callee.includePath(UNKNOWN_PATH, context);
12854
13367
  }
12855
13368
  initialise() {
12856
13369
  super.initialise();
@@ -12889,13 +13402,14 @@ class CatchClause extends NodeBase {
12889
13402
  this.type = type;
12890
13403
  if (param) {
12891
13404
  this.param = new (this.scope.context.getNodeConstructor(param.type))(this, this.scope).parseNode(param);
12892
- this.param.declare('parameter', UNKNOWN_EXPRESSION);
13405
+ this.param.declare('parameter', EMPTY_PATH, UNKNOWN_EXPRESSION);
12893
13406
  }
12894
13407
  this.body = new BlockStatement(this, this.scope.bodyScope).parseNode(body);
12895
13408
  return super.parseNode(esTreeNode);
12896
13409
  }
12897
13410
  }
12898
13411
  CatchClause.prototype.preventChildBlockScope = true;
13412
+ CatchClause.prototype.includeNode = onlyIncludeSelf;
12899
13413
 
12900
13414
  class ChainExpression extends NodeBase {
12901
13415
  // deoptimizations are not relevant as we are not caching values
@@ -12907,17 +13421,22 @@ class ChainExpression extends NodeBase {
12907
13421
  hasEffects(context) {
12908
13422
  return this.expression.hasEffectsAsChainElement(context) === true;
12909
13423
  }
13424
+ includePath(path, context) {
13425
+ this.included = true;
13426
+ this.expression.includePath(path, context);
13427
+ }
12910
13428
  removeAnnotations(code) {
12911
13429
  this.expression.removeAnnotations(code);
12912
13430
  }
12913
- applyDeoptimizations() { }
12914
13431
  }
13432
+ ChainExpression.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
13433
+ ChainExpression.prototype.applyDeoptimizations = doNotDeoptimize;
12915
13434
 
12916
13435
  class ClassBodyScope extends ChildScope {
12917
13436
  constructor(parent, classNode) {
12918
13437
  const { context } = parent;
12919
13438
  super(parent, context);
12920
- this.variables.set('this', (this.thisVariable = new LocalVariable('this', null, classNode, context, 'other')));
13439
+ this.variables.set('this', (this.thisVariable = new LocalVariable('this', null, classNode, EMPTY_PATH, context, 'other')));
12921
13440
  this.instanceScope = new ChildScope(this, context);
12922
13441
  this.instanceScope.variables.set('this', new ThisVariable(context));
12923
13442
  }
@@ -12932,7 +13451,7 @@ class ClassBody extends NodeBase {
12932
13451
  }
12933
13452
  include(context, includeChildrenRecursively) {
12934
13453
  this.included = true;
12935
- this.scope.context.includeVariableInModule(this.scope.thisVariable);
13454
+ this.scope.context.includeVariableInModule(this.scope.thisVariable, UNKNOWN_PATH, context);
12936
13455
  for (const definition of this.body) {
12937
13456
  definition.include(context, includeChildrenRecursively);
12938
13457
  }
@@ -12945,8 +13464,9 @@ class ClassBody extends NodeBase {
12945
13464
  }
12946
13465
  return super.parseNode(esTreeNode);
12947
13466
  }
12948
- applyDeoptimizations() { }
12949
13467
  }
13468
+ ClassBody.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
13469
+ ClassBody.prototype.applyDeoptimizations = doNotDeoptimize;
12950
13470
 
12951
13471
  class ClassExpression extends ClassNode {
12952
13472
  render(code, options, { renderedSurroundingElement } = parseAst_js.BLANK) {
@@ -13017,6 +13537,9 @@ class ConditionalExpression extends NodeBase {
13017
13537
  const unusedBranch = this.usedBranch === this.consequent ? this.alternate : this.consequent;
13018
13538
  this.usedBranch = null;
13019
13539
  unusedBranch.deoptimizePath(UNKNOWN_PATH);
13540
+ if (this.included) {
13541
+ unusedBranch.includePath(UNKNOWN_PATH, createInclusionContext());
13542
+ }
13020
13543
  const { expressionsToBeDeoptimized } = this;
13021
13544
  this.expressionsToBeDeoptimized = parseAst_js.EMPTY_ARRAY;
13022
13545
  for (const expression of expressionsToBeDeoptimized) {
@@ -13074,7 +13597,7 @@ class ConditionalExpression extends NodeBase {
13074
13597
  include(context, includeChildrenRecursively) {
13075
13598
  this.included = true;
13076
13599
  const usedBranch = this.getUsedBranch();
13077
- if (includeChildrenRecursively || this.test.shouldBeIncluded(context) || usedBranch === null) {
13600
+ if (usedBranch === null || includeChildrenRecursively || this.test.shouldBeIncluded(context)) {
13078
13601
  this.test.include(context, includeChildrenRecursively);
13079
13602
  this.consequent.include(context, includeChildrenRecursively);
13080
13603
  this.alternate.include(context, includeChildrenRecursively);
@@ -13083,27 +13606,38 @@ class ConditionalExpression extends NodeBase {
13083
13606
  usedBranch.include(context, includeChildrenRecursively);
13084
13607
  }
13085
13608
  }
13086
- includeCallArguments(context, parameters) {
13609
+ includePath(path, context) {
13610
+ this.included = true;
13611
+ const usedBranch = this.getUsedBranch();
13612
+ if (usedBranch === null || this.test.shouldBeIncluded(context)) {
13613
+ this.consequent.includePath(path, context);
13614
+ this.alternate.includePath(path, context);
13615
+ }
13616
+ else {
13617
+ usedBranch.includePath(path, context);
13618
+ }
13619
+ }
13620
+ includeCallArguments(context, interaction) {
13087
13621
  const usedBranch = this.getUsedBranch();
13088
13622
  if (usedBranch) {
13089
- usedBranch.includeCallArguments(context, parameters);
13623
+ usedBranch.includeCallArguments(context, interaction);
13090
13624
  }
13091
13625
  else {
13092
- this.consequent.includeCallArguments(context, parameters);
13093
- this.alternate.includeCallArguments(context, parameters);
13626
+ this.consequent.includeCallArguments(context, interaction);
13627
+ this.alternate.includeCallArguments(context, interaction);
13094
13628
  }
13095
13629
  }
13096
13630
  removeAnnotations(code) {
13097
13631
  this.test.removeAnnotations(code);
13098
13632
  }
13099
13633
  render(code, options, { isCalleeOfRenderedParent, preventASI, renderedParentType, renderedSurroundingElement } = parseAst_js.BLANK) {
13100
- const usedBranch = this.getUsedBranch();
13101
13634
  if (this.test.included) {
13102
13635
  this.test.render(code, options, { renderedSurroundingElement });
13103
13636
  this.consequent.render(code, options);
13104
13637
  this.alternate.render(code, options);
13105
13638
  }
13106
13639
  else {
13640
+ const usedBranch = this.getUsedBranch();
13107
13641
  const colonPos = findFirstOccurrenceOutsideComment(code.original, ':', this.consequent.end);
13108
13642
  const inclusionStart = findNonWhiteSpace(code.original, (this.consequent.included
13109
13643
  ? findFirstOccurrenceOutsideComment(code.original, '?', this.test.end)
@@ -13135,6 +13669,8 @@ class ConditionalExpression extends NodeBase {
13135
13669
  : (this.usedBranch = testValue ? this.consequent : this.alternate);
13136
13670
  }
13137
13671
  }
13672
+ ConditionalExpression.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
13673
+ ConditionalExpression.prototype.applyDeoptimizations = doNotDeoptimize;
13138
13674
 
13139
13675
  class ContinueStatement extends NodeBase {
13140
13676
  hasEffects(context) {
@@ -13154,7 +13690,7 @@ class ContinueStatement extends NodeBase {
13154
13690
  include(context) {
13155
13691
  this.included = true;
13156
13692
  if (this.label) {
13157
- this.label.include();
13693
+ this.label.include(context);
13158
13694
  context.includedLabels.add(this.label.name);
13159
13695
  }
13160
13696
  else {
@@ -13163,12 +13699,15 @@ class ContinueStatement extends NodeBase {
13163
13699
  context.brokenFlow = true;
13164
13700
  }
13165
13701
  }
13702
+ ContinueStatement.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
13703
+ ContinueStatement.prototype.applyDeoptimizations = doNotDeoptimize;
13166
13704
 
13167
13705
  class DebuggerStatement extends NodeBase {
13168
13706
  hasEffects() {
13169
13707
  return true;
13170
13708
  }
13171
13709
  }
13710
+ DebuggerStatement.prototype.includeNode = onlyIncludeSelf;
13172
13711
 
13173
13712
  class Decorator extends NodeBase {
13174
13713
  hasEffects(context) {
@@ -13176,6 +13715,7 @@ class Decorator extends NodeBase {
13176
13715
  this.expression.hasEffectsOnInteractionAtPath(EMPTY_PATH, NODE_INTERACTION_UNKNOWN_CALL, context));
13177
13716
  }
13178
13717
  }
13718
+ Decorator.prototype.includeNode = onlyIncludeSelf;
13179
13719
 
13180
13720
  function hasLoopBodyEffects(context, body) {
13181
13721
  const { brokenFlow, hasBreak, hasContinue, ignore } = context;
@@ -13215,12 +13755,15 @@ class DoWhileStatement extends NodeBase {
13215
13755
  includeLoopBody(context, this.body, includeChildrenRecursively);
13216
13756
  }
13217
13757
  }
13758
+ DoWhileStatement.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
13759
+ DoWhileStatement.prototype.applyDeoptimizations = doNotDeoptimize;
13218
13760
 
13219
13761
  class EmptyStatement extends NodeBase {
13220
13762
  hasEffects() {
13221
13763
  return false;
13222
13764
  }
13223
13765
  }
13766
+ EmptyStatement.prototype.includeNode = onlyIncludeSelf;
13224
13767
 
13225
13768
  class ExportAllDeclaration extends NodeBase {
13226
13769
  hasEffects() {
@@ -13233,9 +13776,10 @@ class ExportAllDeclaration extends NodeBase {
13233
13776
  render(code, _options, nodeRenderOptions) {
13234
13777
  code.remove(nodeRenderOptions.start, nodeRenderOptions.end);
13235
13778
  }
13236
- applyDeoptimizations() { }
13237
13779
  }
13238
13780
  ExportAllDeclaration.prototype.needsBoundaries = true;
13781
+ ExportAllDeclaration.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
13782
+ ExportAllDeclaration.prototype.applyDeoptimizations = doNotDeoptimize;
13239
13783
 
13240
13784
  class ExportNamedDeclaration extends NodeBase {
13241
13785
  bind() {
@@ -13262,13 +13806,15 @@ class ExportNamedDeclaration extends NodeBase {
13262
13806
  this.declaration.render(code, options, { end, start });
13263
13807
  }
13264
13808
  }
13265
- applyDeoptimizations() { }
13266
13809
  }
13267
13810
  ExportNamedDeclaration.prototype.needsBoundaries = true;
13811
+ ExportNamedDeclaration.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
13812
+ ExportNamedDeclaration.prototype.applyDeoptimizations = doNotDeoptimize;
13268
13813
 
13269
13814
  class ExportSpecifier extends NodeBase {
13270
- applyDeoptimizations() { }
13271
13815
  }
13816
+ ExportSpecifier.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
13817
+ ExportSpecifier.prototype.applyDeoptimizations = doNotDeoptimize;
13272
13818
 
13273
13819
  class ForInStatement extends NodeBase {
13274
13820
  createScope(parentScope) {
@@ -13286,11 +13832,18 @@ class ForInStatement extends NodeBase {
13286
13832
  const { body, deoptimized, left, right } = this;
13287
13833
  if (!deoptimized)
13288
13834
  this.applyDeoptimizations();
13289
- this.included = true;
13835
+ if (!this.included)
13836
+ this.includeNode(context);
13290
13837
  left.includeAsAssignmentTarget(context, includeChildrenRecursively || true, false);
13291
13838
  right.include(context, includeChildrenRecursively);
13292
13839
  includeLoopBody(context, body, includeChildrenRecursively);
13293
13840
  }
13841
+ includeNode(context) {
13842
+ this.included = true;
13843
+ if (!this.deoptimized)
13844
+ this.applyDeoptimizations();
13845
+ this.right.includePath(UNKNOWN_PATH, context);
13846
+ }
13294
13847
  initialise() {
13295
13848
  super.initialise();
13296
13849
  this.left.setAssignedValue(UNKNOWN_EXPRESSION);
@@ -13331,11 +13884,18 @@ class ForOfStatement extends NodeBase {
13331
13884
  const { body, deoptimized, left, right } = this;
13332
13885
  if (!deoptimized)
13333
13886
  this.applyDeoptimizations();
13334
- this.included = true;
13887
+ if (!this.included)
13888
+ this.includeNode(context);
13335
13889
  left.includeAsAssignmentTarget(context, includeChildrenRecursively || true, false);
13336
13890
  right.include(context, includeChildrenRecursively);
13337
13891
  includeLoopBody(context, body, includeChildrenRecursively);
13338
13892
  }
13893
+ includeNode(context) {
13894
+ this.included = true;
13895
+ if (!this.deoptimized)
13896
+ this.applyDeoptimizations();
13897
+ this.right.includePath(UNKNOWN_PATH, context);
13898
+ }
13339
13899
  initialise() {
13340
13900
  super.initialise();
13341
13901
  this.left.setAssignedValue(UNKNOWN_EXPRESSION);
@@ -13371,7 +13931,9 @@ class ForStatement extends NodeBase {
13371
13931
  }
13372
13932
  include(context, includeChildrenRecursively) {
13373
13933
  this.included = true;
13374
- this.init?.include(context, includeChildrenRecursively, { asSingleStatement: true });
13934
+ this.init?.include(context, includeChildrenRecursively, {
13935
+ asSingleStatement: true
13936
+ });
13375
13937
  this.test?.include(context, includeChildrenRecursively);
13376
13938
  this.update?.include(context, includeChildrenRecursively);
13377
13939
  includeLoopBody(context, this.body, includeChildrenRecursively);
@@ -13383,6 +13945,8 @@ class ForStatement extends NodeBase {
13383
13945
  this.body.render(code, options);
13384
13946
  }
13385
13947
  }
13948
+ ForStatement.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
13949
+ ForStatement.prototype.applyDeoptimizations = doNotDeoptimize;
13386
13950
 
13387
13951
  class FunctionExpression extends FunctionNode {
13388
13952
  createScope(parentScope) {
@@ -13414,9 +13978,9 @@ class TrackingScope extends BlockScope {
13414
13978
  super(...arguments);
13415
13979
  this.hoistedDeclarations = [];
13416
13980
  }
13417
- addDeclaration(identifier, context, init, kind) {
13981
+ addDeclaration(identifier, context, init, destructuredInitPath, kind) {
13418
13982
  this.hoistedDeclarations.push(identifier);
13419
- return super.addDeclaration(identifier, context, init, kind);
13983
+ return super.addDeclaration(identifier, context, init, destructuredInitPath, kind);
13420
13984
  }
13421
13985
  }
13422
13986
 
@@ -13515,7 +14079,6 @@ class IfStatement extends NodeBase {
13515
14079
  }
13516
14080
  this.renderHoistedDeclarations(hoistedDeclarations, code, getPropertyAccess);
13517
14081
  }
13518
- applyDeoptimizations() { }
13519
14082
  getTestValue() {
13520
14083
  if (this.testValue === unset) {
13521
14084
  return (this.testValue = tryCastLiteralValueToBoolean(this.test.getLiteralValueAtPath(EMPTY_PATH, SHARED_RECURSION_TRACKER, this)));
@@ -13584,6 +14147,8 @@ class IfStatement extends NodeBase {
13584
14147
  return false;
13585
14148
  }
13586
14149
  }
14150
+ IfStatement.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
14151
+ IfStatement.prototype.applyDeoptimizations = doNotDeoptimize;
13587
14152
 
13588
14153
  class ImportAttribute extends NodeBase {
13589
14154
  }
@@ -13601,13 +14166,15 @@ class ImportDeclaration extends NodeBase {
13601
14166
  render(code, _options, nodeRenderOptions) {
13602
14167
  code.remove(nodeRenderOptions.start, nodeRenderOptions.end);
13603
14168
  }
13604
- applyDeoptimizations() { }
13605
14169
  }
13606
14170
  ImportDeclaration.prototype.needsBoundaries = true;
14171
+ ImportDeclaration.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
14172
+ ImportDeclaration.prototype.applyDeoptimizations = doNotDeoptimize;
13607
14173
 
13608
14174
  class ImportDefaultSpecifier extends NodeBase {
13609
- applyDeoptimizations() { }
13610
14175
  }
14176
+ ImportDefaultSpecifier.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
14177
+ ImportDefaultSpecifier.prototype.applyDeoptimizations = doNotDeoptimize;
13611
14178
 
13612
14179
  function isReassignedExportsMember(variable, exportNamesByVariable) {
13613
14180
  return (variable.renderBaseName !== null && exportNamesByVariable.has(variable) && variable.isReassigned);
@@ -13616,28 +14183,33 @@ function isReassignedExportsMember(variable, exportNamesByVariable) {
13616
14183
  class VariableDeclarator extends NodeBase {
13617
14184
  declareDeclarator(kind, isUsingDeclaration) {
13618
14185
  this.isUsingDeclaration = isUsingDeclaration;
13619
- this.id.declare(kind, this.init || UNDEFINED_EXPRESSION);
14186
+ this.id.declare(kind, EMPTY_PATH, this.init || UNDEFINED_EXPRESSION);
13620
14187
  }
13621
14188
  deoptimizePath(path) {
13622
14189
  this.id.deoptimizePath(path);
13623
14190
  }
13624
14191
  hasEffects(context) {
13625
- if (!this.deoptimized)
13626
- this.applyDeoptimizations();
13627
14192
  const initEffect = this.init?.hasEffects(context);
13628
14193
  this.id.markDeclarationReached();
13629
- return initEffect || this.id.hasEffects(context) || this.isUsingDeclaration;
14194
+ return (initEffect ||
14195
+ this.isUsingDeclaration ||
14196
+ this.id.hasEffects(context) ||
14197
+ (this.scope.context.options.treeshake
14198
+ .propertyReadSideEffects &&
14199
+ this.id.hasEffectsWhenDestructuring(context, EMPTY_PATH, this.init || UNDEFINED_EXPRESSION)));
13630
14200
  }
13631
14201
  include(context, includeChildrenRecursively) {
13632
- const { deoptimized, id, init } = this;
13633
- if (!deoptimized)
13634
- this.applyDeoptimizations();
13635
- this.included = true;
14202
+ const { id, init } = this;
14203
+ if (!this.included)
14204
+ this.includeNode();
13636
14205
  init?.include(context, includeChildrenRecursively);
13637
14206
  id.markDeclarationReached();
13638
- if (includeChildrenRecursively || id.shouldBeIncluded(context)) {
14207
+ if (includeChildrenRecursively) {
13639
14208
  id.include(context, includeChildrenRecursively);
13640
14209
  }
14210
+ else {
14211
+ id.includeDestructuredIfNecessary(context, EMPTY_PATH, init || UNDEFINED_EXPRESSION);
14212
+ }
13641
14213
  }
13642
14214
  removeAnnotations(code) {
13643
14215
  this.init?.removeAnnotations(code);
@@ -13667,8 +14239,8 @@ class VariableDeclarator extends NodeBase {
13667
14239
  code.appendLeft(end, `${_}=${_}void 0`);
13668
14240
  }
13669
14241
  }
13670
- applyDeoptimizations() {
13671
- this.deoptimized = true;
14242
+ includeNode() {
14243
+ this.included = true;
13672
14244
  const { id, init } = this;
13673
14245
  if (init && id instanceof Identifier && init instanceof ClassExpression && !init.id) {
13674
14246
  const { name, variable } = id;
@@ -13680,11 +14252,14 @@ class VariableDeclarator extends NodeBase {
13680
14252
  }
13681
14253
  }
13682
14254
  }
14255
+ VariableDeclarator.prototype.applyDeoptimizations = doNotDeoptimize;
13683
14256
 
13684
14257
  class ImportExpression extends NodeBase {
13685
14258
  constructor() {
13686
14259
  super(...arguments);
13687
14260
  this.inlineNamespace = null;
14261
+ this.hasUnknownAccessedKey = false;
14262
+ this.accessedPropKey = new Set();
13688
14263
  this.attributes = null;
13689
14264
  this.mechanism = null;
13690
14265
  this.namespaceExportName = undefined;
@@ -13717,12 +14292,15 @@ class ImportExpression extends NodeBase {
13717
14292
  if (parent2 instanceof ExpressionStatement) {
13718
14293
  return parseAst_js.EMPTY_ARRAY;
13719
14294
  }
13720
- // Case 1: const { foo } = await import('bar')
14295
+ // Case 1: const { foo } / module = await import('bar')
13721
14296
  if (parent2 instanceof VariableDeclarator) {
13722
14297
  const declaration = parent2.id;
13723
- return declaration instanceof ObjectPattern
13724
- ? getDeterministicObjectDestructure(declaration)
13725
- : undefined;
14298
+ if (declaration instanceof Identifier) {
14299
+ return this.hasUnknownAccessedKey ? undefined : [...this.accessedPropKey];
14300
+ }
14301
+ if (declaration instanceof ObjectPattern) {
14302
+ return getDeterministicObjectDestructure(declaration);
14303
+ }
13726
14304
  }
13727
14305
  // Case 2: (await import('bar')).foo
13728
14306
  if (parent2 instanceof MemberExpression) {
@@ -13772,13 +14350,30 @@ class ImportExpression extends NodeBase {
13772
14350
  return true;
13773
14351
  }
13774
14352
  include(context, includeChildrenRecursively) {
13775
- if (!this.included) {
13776
- this.included = true;
13777
- this.scope.context.includeDynamicImport(this);
13778
- this.scope.addAccessedDynamicImport(this);
13779
- }
14353
+ if (!this.included)
14354
+ this.includeNode();
13780
14355
  this.source.include(context, includeChildrenRecursively);
13781
14356
  }
14357
+ includeNode() {
14358
+ this.included = true;
14359
+ this.scope.context.includeDynamicImport(this);
14360
+ this.scope.addAccessedDynamicImport(this);
14361
+ }
14362
+ includePath(path) {
14363
+ if (!this.included)
14364
+ this.includeNode();
14365
+ // Technically, this is not correct as dynamic imports return a Promise.
14366
+ if (this.hasUnknownAccessedKey)
14367
+ return;
14368
+ if (path[0] === UnknownKey) {
14369
+ this.hasUnknownAccessedKey = true;
14370
+ }
14371
+ else if (typeof path[0] === 'string') {
14372
+ this.accessedPropKey.add(path[0]);
14373
+ }
14374
+ // Update included paths
14375
+ this.scope.context.includeDynamicImport(this);
14376
+ }
13782
14377
  initialise() {
13783
14378
  super.initialise();
13784
14379
  this.scope.context.addDynamicImport(this);
@@ -13847,7 +14442,6 @@ class ImportExpression extends NodeBase {
13847
14442
  setInternalResolution(inlineNamespace) {
13848
14443
  this.inlineNamespace = inlineNamespace;
13849
14444
  }
13850
- applyDeoptimizations() { }
13851
14445
  getDynamicImportMechanismAndHelper(resolution, exportMode, { compact, dynamicImportInCjs, format, generatedCode: { arrowFunctions }, interop }, { _, getDirectReturnFunction, getDirectReturnIifeLeft }, pluginDriver) {
13852
14446
  const mechanism = pluginDriver.hookFirstSync('renderDynamicImport', [
13853
14447
  {
@@ -13937,6 +14531,7 @@ class ImportExpression extends NodeBase {
13937
14531
  return { helper: null, mechanism: null };
13938
14532
  }
13939
14533
  }
14534
+ ImportExpression.prototype.applyDeoptimizations = doNotDeoptimize;
13940
14535
  function getInteropHelper(resolution, exportMode, interop) {
13941
14536
  return exportMode === 'external'
13942
14537
  ? namespaceInteropHelpersByInteropType[interop(resolution instanceof ExternalModule ? resolution.id : null)]
@@ -13960,12 +14555,14 @@ function getDeterministicObjectDestructure(objectPattern) {
13960
14555
  }
13961
14556
 
13962
14557
  class ImportNamespaceSpecifier extends NodeBase {
13963
- applyDeoptimizations() { }
13964
14558
  }
14559
+ ImportNamespaceSpecifier.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
14560
+ ImportNamespaceSpecifier.prototype.applyDeoptimizations = doNotDeoptimize;
13965
14561
 
13966
14562
  class ImportSpecifier extends NodeBase {
13967
- applyDeoptimizations() { }
13968
14563
  }
14564
+ ImportSpecifier.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
14565
+ ImportSpecifier.prototype.applyDeoptimizations = doNotDeoptimize;
13969
14566
 
13970
14567
  class JSXIdentifier extends IdentifierBase {
13971
14568
  constructor() {
@@ -13982,6 +14579,29 @@ class JSXIdentifier extends IdentifierBase {
13982
14579
  this.isNativeElement = true;
13983
14580
  }
13984
14581
  }
14582
+ include(context) {
14583
+ if (!this.included)
14584
+ this.includeNode(context);
14585
+ }
14586
+ includeNode(context) {
14587
+ this.included = true;
14588
+ if (!this.deoptimized)
14589
+ this.applyDeoptimizations();
14590
+ if (this.variable !== null) {
14591
+ this.scope.context.includeVariableInModule(this.variable, EMPTY_PATH, context);
14592
+ }
14593
+ }
14594
+ includePath(path, context) {
14595
+ if (!this.included) {
14596
+ this.included = true;
14597
+ if (this.variable !== null) {
14598
+ this.scope.context.includeVariableInModule(this.variable, path, context);
14599
+ }
14600
+ }
14601
+ else if (path.length > 0) {
14602
+ this.variable?.includePath(path, context);
14603
+ }
14604
+ }
13985
14605
  render(code, { snippets: { getPropertyAccess }, useOriginalName }) {
13986
14606
  if (this.variable) {
13987
14607
  const name = this.variable.getName(getPropertyAccess, useOriginalName);
@@ -14043,6 +14663,7 @@ class JSXAttribute extends NodeBase {
14043
14663
  }
14044
14664
  }
14045
14665
  }
14666
+ JSXAttribute.prototype.includeNode = onlyIncludeSelf;
14046
14667
 
14047
14668
  class JSXClosingBase extends NodeBase {
14048
14669
  render(code, options) {
@@ -14055,6 +14676,7 @@ class JSXClosingBase extends NodeBase {
14055
14676
  }
14056
14677
  }
14057
14678
  }
14679
+ JSXClosingBase.prototype.includeNode = onlyIncludeSelf;
14058
14680
 
14059
14681
  class JSXClosingElement extends JSXClosingBase {
14060
14682
  }
@@ -14075,8 +14697,15 @@ class JSXSpreadAttribute extends NodeBase {
14075
14697
 
14076
14698
  class JSXEmptyExpression extends NodeBase {
14077
14699
  }
14700
+ JSXEmptyExpression.prototype.includeNode = onlyIncludeSelf;
14078
14701
 
14079
14702
  class JSXExpressionContainer extends NodeBase {
14703
+ includeNode(context) {
14704
+ this.included = true;
14705
+ if (!this.deoptimized)
14706
+ this.applyDeoptimizations();
14707
+ this.expression.includePath(UNKNOWN_PATH, context);
14708
+ }
14080
14709
  render(code, options) {
14081
14710
  const { mode } = this.scope.context.options.jsx;
14082
14711
  if (mode !== 'preserve') {
@@ -14097,7 +14726,7 @@ function getRenderedJsxChildren(children) {
14097
14726
  return renderedChildren;
14098
14727
  }
14099
14728
 
14100
- function getAndIncludeFactoryVariable(factory, preserve, importSource, node) {
14729
+ function getAndIncludeFactoryVariable(factory, preserve, importSource, node, context) {
14101
14730
  const [baseName, nestedName] = factory.split('.');
14102
14731
  let factoryVariable;
14103
14732
  if (importSource) {
@@ -14105,7 +14734,7 @@ function getAndIncludeFactoryVariable(factory, preserve, importSource, node) {
14105
14734
  if (preserve) {
14106
14735
  // This pretends we are accessing an included global variable of the same name
14107
14736
  const globalVariable = node.scope.findGlobal(baseName);
14108
- globalVariable.include();
14737
+ globalVariable.includePath(UNKNOWN_PATH, context);
14109
14738
  // This excludes this variable from renaming
14110
14739
  factoryVariable.globalName = baseName;
14111
14740
  }
@@ -14113,7 +14742,7 @@ function getAndIncludeFactoryVariable(factory, preserve, importSource, node) {
14113
14742
  else {
14114
14743
  factoryVariable = node.scope.findGlobal(baseName);
14115
14744
  }
14116
- node.scope.context.includeVariableInModule(factoryVariable);
14745
+ node.scope.context.includeVariableInModule(factoryVariable, UNKNOWN_PATH, context);
14117
14746
  if (factoryVariable instanceof LocalVariable) {
14118
14747
  factoryVariable.consolidateInitializers();
14119
14748
  factoryVariable.addUsedPlace(node);
@@ -14136,16 +14765,20 @@ class JSXElementBase extends NodeBase {
14136
14765
  }
14137
14766
  }
14138
14767
  include(context, includeChildrenRecursively) {
14139
- if (!this.included) {
14140
- const { factory, importSource, mode } = this.jsxMode;
14141
- if (factory) {
14142
- this.factory = factory;
14143
- this.factoryVariable = getAndIncludeFactoryVariable(factory, mode === 'preserve', importSource, this);
14144
- }
14768
+ if (!this.included)
14769
+ this.includeNode(context);
14770
+ for (const child of this.children) {
14771
+ child.include(context, includeChildrenRecursively);
14772
+ }
14773
+ }
14774
+ includeNode(context) {
14775
+ this.included = true;
14776
+ const { factory, importSource, mode } = this.jsxMode;
14777
+ if (factory) {
14778
+ this.factory = factory;
14779
+ this.factoryVariable = getAndIncludeFactoryVariable(factory, mode === 'preserve', importSource, this, context);
14145
14780
  }
14146
- super.include(context, includeChildrenRecursively);
14147
14781
  }
14148
- applyDeoptimizations() { }
14149
14782
  getRenderingMode() {
14150
14783
  const jsx = this.scope.context.options.jsx;
14151
14784
  const { mode, factory, importSource } = jsx;
@@ -14183,8 +14816,14 @@ class JSXElementBase extends NodeBase {
14183
14816
  return { childrenEnd, firstChild, hasMultipleChildren };
14184
14817
  }
14185
14818
  }
14819
+ JSXElementBase.prototype.applyDeoptimizations = doNotDeoptimize;
14186
14820
 
14187
14821
  class JSXElement extends JSXElementBase {
14822
+ include(context, includeChildrenRecursively) {
14823
+ super.include(context, includeChildrenRecursively);
14824
+ this.openingElement.include(context, includeChildrenRecursively);
14825
+ this.closingElement?.include(context, includeChildrenRecursively);
14826
+ }
14188
14827
  render(code, options) {
14189
14828
  switch (this.jsxMode.mode) {
14190
14829
  case 'classic': {
@@ -14336,6 +14975,11 @@ class JSXElement extends JSXElementBase {
14336
14975
  }
14337
14976
 
14338
14977
  class JSXFragment extends JSXElementBase {
14978
+ include(context, includeChildrenRecursively) {
14979
+ super.include(context, includeChildrenRecursively);
14980
+ this.openingFragment.include(context, includeChildrenRecursively);
14981
+ this.closingFragment.include(context, includeChildrenRecursively);
14982
+ }
14339
14983
  render(code, options) {
14340
14984
  switch (this.jsxMode.mode) {
14341
14985
  case 'classic': {
@@ -14385,10 +15029,22 @@ class JSXFragment extends JSXElementBase {
14385
15029
  }
14386
15030
 
14387
15031
  class JSXMemberExpression extends NodeBase {
15032
+ includeNode(context) {
15033
+ this.included = true;
15034
+ if (!this.deoptimized)
15035
+ this.applyDeoptimizations();
15036
+ this.object.includePath([this.property.name], context);
15037
+ }
15038
+ includePath(path, context) {
15039
+ if (!this.included)
15040
+ this.includeNode(context);
15041
+ this.object.includePath([this.property.name, ...path], context);
15042
+ }
14388
15043
  }
14389
15044
 
14390
15045
  class JSXNamespacedName extends NodeBase {
14391
15046
  }
15047
+ JSXNamespacedName.prototype.includeNode = onlyIncludeSelf;
14392
15048
 
14393
15049
  class JSXOpeningElement extends NodeBase {
14394
15050
  render(code, options, { jsxMode = this.scope.context.options.jsx.mode } = {}) {
@@ -14398,6 +15054,7 @@ class JSXOpeningElement extends NodeBase {
14398
15054
  }
14399
15055
  }
14400
15056
  }
15057
+ JSXOpeningElement.prototype.includeNode = onlyIncludeSelf;
14401
15058
 
14402
15059
  class JSXOpeningFragment extends NodeBase {
14403
15060
  constructor() {
@@ -14405,22 +15062,22 @@ class JSXOpeningFragment extends NodeBase {
14405
15062
  this.fragment = null;
14406
15063
  this.fragmentVariable = null;
14407
15064
  }
14408
- include(context, includeChildrenRecursively) {
14409
- if (!this.included) {
14410
- const jsx = this.scope.context.options.jsx;
14411
- if (jsx.mode === 'automatic') {
14412
- this.fragment = 'Fragment';
14413
- this.fragmentVariable = getAndIncludeFactoryVariable('Fragment', false, jsx.jsxImportSource, this);
14414
- }
14415
- else {
14416
- const { fragment, importSource, mode } = jsx;
14417
- if (fragment != null) {
14418
- this.fragment = fragment;
14419
- this.fragmentVariable = getAndIncludeFactoryVariable(fragment, mode === 'preserve', importSource, this);
14420
- }
15065
+ includeNode(context) {
15066
+ this.included = true;
15067
+ if (!this.deoptimized)
15068
+ this.applyDeoptimizations();
15069
+ const jsx = this.scope.context.options.jsx;
15070
+ if (jsx.mode === 'automatic') {
15071
+ this.fragment = 'Fragment';
15072
+ this.fragmentVariable = getAndIncludeFactoryVariable('Fragment', false, jsx.jsxImportSource, this, context);
15073
+ }
15074
+ else {
15075
+ const { fragment, importSource, mode } = jsx;
15076
+ if (fragment != null) {
15077
+ this.fragment = fragment;
15078
+ this.fragmentVariable = getAndIncludeFactoryVariable(fragment, mode === 'preserve', importSource, this, context);
14421
15079
  }
14422
15080
  }
14423
- super.include(context, includeChildrenRecursively);
14424
15081
  }
14425
15082
  render(code, options) {
14426
15083
  const { mode } = this.scope.context.options.jsx;
@@ -14457,6 +15114,7 @@ class JSXText extends NodeBase {
14457
15114
  }
14458
15115
  }
14459
15116
  }
15117
+ JSXText.prototype.includeNode = onlyIncludeSelf;
14460
15118
 
14461
15119
  class LabeledStatement extends NodeBase {
14462
15120
  hasEffects(context) {
@@ -14478,17 +15136,22 @@ class LabeledStatement extends NodeBase {
14478
15136
  return bodyHasEffects;
14479
15137
  }
14480
15138
  include(context, includeChildrenRecursively) {
14481
- this.included = true;
15139
+ if (!this.included)
15140
+ this.includeNode(context);
14482
15141
  const { brokenFlow, includedLabels } = context;
14483
15142
  context.includedLabels = new Set();
14484
15143
  this.body.include(context, includeChildrenRecursively);
14485
15144
  if (includeChildrenRecursively || context.includedLabels.has(this.label.name)) {
14486
- this.label.include();
15145
+ this.label.include(context);
14487
15146
  context.includedLabels.delete(this.label.name);
14488
15147
  context.brokenFlow = brokenFlow;
14489
15148
  }
14490
15149
  context.includedLabels = new Set([...includedLabels, ...context.includedLabels]);
14491
15150
  }
15151
+ includeNode(context) {
15152
+ this.included = true;
15153
+ this.body.includePath(UNKNOWN_PATH, context);
15154
+ }
14492
15155
  render(code, options) {
14493
15156
  if (this.label.included) {
14494
15157
  this.label.render(code, options);
@@ -14499,6 +15162,7 @@ class LabeledStatement extends NodeBase {
14499
15162
  this.body.render(code, options);
14500
15163
  }
14501
15164
  }
15165
+ LabeledStatement.prototype.applyDeoptimizations = doNotDeoptimize;
14502
15166
 
14503
15167
  class LogicalExpression extends NodeBase {
14504
15168
  constructor() {
@@ -14515,10 +15179,10 @@ class LogicalExpression extends NodeBase {
14515
15179
  this.flags = setFlag(this.flags, 65536 /* Flag.isBranchResolutionAnalysed */, value);
14516
15180
  }
14517
15181
  get hasDeoptimizedCache() {
14518
- return isFlagSet(this.flags, 16777216 /* Flag.hasDeoptimizedCache */);
15182
+ return isFlagSet(this.flags, 33554432 /* Flag.hasDeoptimizedCache */);
14519
15183
  }
14520
15184
  set hasDeoptimizedCache(value) {
14521
- this.flags = setFlag(this.flags, 16777216 /* Flag.hasDeoptimizedCache */, value);
15185
+ this.flags = setFlag(this.flags, 33554432 /* Flag.hasDeoptimizedCache */, value);
14522
15186
  }
14523
15187
  deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
14524
15188
  this.left.deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker);
@@ -14531,6 +15195,10 @@ class LogicalExpression extends NodeBase {
14531
15195
  const unusedBranch = this.usedBranch === this.left ? this.right : this.left;
14532
15196
  this.usedBranch = null;
14533
15197
  unusedBranch.deoptimizePath(UNKNOWN_PATH);
15198
+ if (this.included) {
15199
+ // As we are not tracking inclusions, we just include everything
15200
+ unusedBranch.includePath(UNKNOWN_PATH, createInclusionContext());
15201
+ }
14534
15202
  }
14535
15203
  const { scope: { context }, expressionsToBeDeoptimized } = this;
14536
15204
  this.expressionsToBeDeoptimized = parseAst_js.EMPTY_ARRAY;
@@ -14576,16 +15244,17 @@ class LogicalExpression extends NodeBase {
14576
15244
  }
14577
15245
  getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin) {
14578
15246
  const usedBranch = this.getUsedBranch();
14579
- if (!usedBranch)
14580
- return [
14581
- new MultiExpression([
14582
- this.left.getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin)[0],
14583
- this.right.getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin)[0]
14584
- ]),
14585
- false
14586
- ];
14587
- this.expressionsToBeDeoptimized.push(origin);
14588
- return usedBranch.getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin);
15247
+ if (usedBranch) {
15248
+ this.expressionsToBeDeoptimized.push(origin);
15249
+ return usedBranch.getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin);
15250
+ }
15251
+ return [
15252
+ new MultiExpression([
15253
+ this.left.getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin)[0],
15254
+ this.right.getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin)[0]
15255
+ ]),
15256
+ false
15257
+ ];
14589
15258
  }
14590
15259
  hasEffects(context) {
14591
15260
  if (this.left.hasEffects(context)) {
@@ -14598,18 +15267,18 @@ class LogicalExpression extends NodeBase {
14598
15267
  }
14599
15268
  hasEffectsOnInteractionAtPath(path, interaction, context) {
14600
15269
  const usedBranch = this.getUsedBranch();
14601
- if (!usedBranch) {
14602
- return (this.left.hasEffectsOnInteractionAtPath(path, interaction, context) ||
14603
- this.right.hasEffectsOnInteractionAtPath(path, interaction, context));
15270
+ if (usedBranch) {
15271
+ return usedBranch.hasEffectsOnInteractionAtPath(path, interaction, context);
14604
15272
  }
14605
- return usedBranch.hasEffectsOnInteractionAtPath(path, interaction, context);
15273
+ return (this.left.hasEffectsOnInteractionAtPath(path, interaction, context) ||
15274
+ this.right.hasEffectsOnInteractionAtPath(path, interaction, context));
14606
15275
  }
14607
15276
  include(context, includeChildrenRecursively) {
14608
15277
  this.included = true;
14609
15278
  const usedBranch = this.getUsedBranch();
14610
15279
  if (includeChildrenRecursively ||
14611
- (usedBranch === this.right && this.left.shouldBeIncluded(context)) ||
14612
- !usedBranch) {
15280
+ !usedBranch ||
15281
+ (usedBranch === this.right && this.left.shouldBeIncluded(context))) {
14613
15282
  this.left.include(context, includeChildrenRecursively);
14614
15283
  this.right.include(context, includeChildrenRecursively);
14615
15284
  }
@@ -14617,6 +15286,17 @@ class LogicalExpression extends NodeBase {
14617
15286
  usedBranch.include(context, includeChildrenRecursively);
14618
15287
  }
14619
15288
  }
15289
+ includePath(path, context) {
15290
+ this.included = true;
15291
+ const usedBranch = this.getUsedBranch();
15292
+ if (!usedBranch || (usedBranch === this.right && this.left.shouldBeIncluded(context))) {
15293
+ this.left.includePath(path, context);
15294
+ this.right.includePath(path, context);
15295
+ }
15296
+ else {
15297
+ usedBranch.includePath(path, context);
15298
+ }
15299
+ }
14620
15300
  removeAnnotations(code) {
14621
15301
  this.left.removeAnnotations(code);
14622
15302
  }
@@ -14669,6 +15349,8 @@ class LogicalExpression extends NodeBase {
14669
15349
  return this.usedBranch;
14670
15350
  }
14671
15351
  }
15352
+ LogicalExpression.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
15353
+ LogicalExpression.prototype.applyDeoptimizations = doNotDeoptimize;
14672
15354
 
14673
15355
  class NewExpression extends NodeBase {
14674
15356
  hasEffects(context) {
@@ -14688,16 +15370,21 @@ class NewExpression extends NodeBase {
14688
15370
  return path.length > 0 || type !== INTERACTION_ACCESSED;
14689
15371
  }
14690
15372
  include(context, includeChildrenRecursively) {
14691
- if (!this.deoptimized)
14692
- this.applyDeoptimizations();
14693
15373
  if (includeChildrenRecursively) {
14694
15374
  super.include(context, includeChildrenRecursively);
14695
15375
  }
14696
15376
  else {
14697
- this.included = true;
15377
+ if (!this.included)
15378
+ this.includeNode(context);
14698
15379
  this.callee.include(context, false);
14699
15380
  }
14700
- this.callee.includeCallArguments(context, this.arguments);
15381
+ this.callee.includeCallArguments(context, this.interaction);
15382
+ }
15383
+ includeNode(context) {
15384
+ this.included = true;
15385
+ if (!this.deoptimized)
15386
+ this.applyDeoptimizations();
15387
+ this.callee.includePath(UNKNOWN_PATH, context);
14701
15388
  }
14702
15389
  initialise() {
14703
15390
  super.initialise();
@@ -14726,6 +15413,7 @@ class ObjectExpression extends NodeBase {
14726
15413
  constructor() {
14727
15414
  super(...arguments);
14728
15415
  this.objectEntity = null;
15416
+ this.protoProp = null;
14729
15417
  }
14730
15418
  deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
14731
15419
  this.getObjectEntity().deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker);
@@ -14745,15 +15433,43 @@ class ObjectExpression extends NodeBase {
14745
15433
  hasEffectsOnInteractionAtPath(path, interaction, context) {
14746
15434
  return this.getObjectEntity().hasEffectsOnInteractionAtPath(path, interaction, context);
14747
15435
  }
15436
+ include(context, includeChildrenRecursively) {
15437
+ if (!this.included)
15438
+ this.includeNode(context);
15439
+ this.getObjectEntity().include(context, includeChildrenRecursively);
15440
+ this.protoProp?.include(context, includeChildrenRecursively);
15441
+ }
15442
+ includeNode(context) {
15443
+ this.included = true;
15444
+ this.protoProp?.includePath(UNKNOWN_PATH, context);
15445
+ }
15446
+ includePath(path, context) {
15447
+ if (!this.included)
15448
+ this.includeNode(context);
15449
+ this.getObjectEntity().includePath(path, context);
15450
+ }
14748
15451
  render(code, options, { renderedSurroundingElement } = parseAst_js.BLANK) {
14749
- super.render(code, options);
14750
15452
  if (renderedSurroundingElement === parseAst_js.ExpressionStatement ||
14751
15453
  renderedSurroundingElement === parseAst_js.ArrowFunctionExpression) {
14752
15454
  code.appendRight(this.start, '(');
14753
15455
  code.prependLeft(this.end, ')');
14754
15456
  }
15457
+ if (this.properties.length > 0) {
15458
+ const separatedNodes = getCommaSeparatedNodesWithBoundaries(this.properties, code, this.start + 1, this.end - 1);
15459
+ let lastSeparatorPos = null;
15460
+ for (const { node, separator, start, end } of separatedNodes) {
15461
+ if (!node.included) {
15462
+ treeshakeNode(node, code, start, end);
15463
+ continue;
15464
+ }
15465
+ lastSeparatorPos = separator;
15466
+ node.render(code, options);
15467
+ }
15468
+ if (lastSeparatorPos) {
15469
+ code.remove(lastSeparatorPos, this.end - 1);
15470
+ }
15471
+ }
14755
15472
  }
14756
- applyDeoptimizations() { }
14757
15473
  getObjectEntity() {
14758
15474
  if (this.objectEntity !== null) {
14759
15475
  return this.objectEntity;
@@ -14782,6 +15498,7 @@ class ObjectExpression extends NodeBase {
14782
15498
  ? property.key.name
14783
15499
  : String(property.key.value);
14784
15500
  if (key === '__proto__' && property.kind === 'init') {
15501
+ this.protoProp = property;
14785
15502
  prototype =
14786
15503
  property.value instanceof Literal && property.value.value === null
14787
15504
  ? null
@@ -14794,6 +15511,7 @@ class ObjectExpression extends NodeBase {
14794
15511
  return (this.objectEntity = new ObjectEntity(properties, prototype));
14795
15512
  }
14796
15513
  }
15514
+ ObjectExpression.prototype.applyDeoptimizations = doNotDeoptimize;
14797
15515
 
14798
15516
  class PanicError extends NodeBase {
14799
15517
  initialise() {
@@ -14820,6 +15538,7 @@ class ParseError extends NodeBase {
14820
15538
 
14821
15539
  class PrivateIdentifier extends NodeBase {
14822
15540
  }
15541
+ PrivateIdentifier.prototype.includeNode = onlyIncludeSelf;
14823
15542
 
14824
15543
  class Program extends NodeBase {
14825
15544
  constructor() {
@@ -14887,14 +15606,11 @@ class Program extends NodeBase {
14887
15606
  super.render(code, options);
14888
15607
  }
14889
15608
  }
14890
- applyDeoptimizations() { }
14891
15609
  }
15610
+ Program.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
15611
+ Program.prototype.applyDeoptimizations = doNotDeoptimize;
14892
15612
 
14893
15613
  class Property extends MethodBase {
14894
- constructor() {
14895
- super(...arguments);
14896
- this.declarationInit = null;
14897
- }
14898
15614
  //declare method: boolean;
14899
15615
  get method() {
14900
15616
  return isFlagSet(this.flags, 262144 /* Flag.method */);
@@ -14909,17 +15625,41 @@ class Property extends MethodBase {
14909
15625
  set shorthand(value) {
14910
15626
  this.flags = setFlag(this.flags, 524288 /* Flag.shorthand */, value);
14911
15627
  }
14912
- declare(kind, init) {
14913
- this.declarationInit = init;
14914
- return this.value.declare(kind, UNKNOWN_EXPRESSION);
15628
+ declare(kind, destructuredInitPath, init) {
15629
+ return this.value.declare(kind, this.getPathInProperty(destructuredInitPath), init);
15630
+ }
15631
+ deoptimizeAssignment(destructuredInitPath, init) {
15632
+ this.value.deoptimizeAssignment?.(this.getPathInProperty(destructuredInitPath), init);
14915
15633
  }
14916
15634
  hasEffects(context) {
14917
- if (!this.deoptimized)
14918
- this.applyDeoptimizations();
14919
- const propertyReadSideEffects = this.scope.context.options.treeshake.propertyReadSideEffects;
14920
- return ((this.parent.type === 'ObjectPattern' && propertyReadSideEffects === 'always') ||
14921
- this.key.hasEffects(context) ||
14922
- this.value.hasEffects(context));
15635
+ return this.key.hasEffects(context) || this.value.hasEffects(context);
15636
+ }
15637
+ hasEffectsWhenDestructuring(context, destructuredInitPath, init) {
15638
+ return this.value.hasEffectsWhenDestructuring?.(context, this.getPathInProperty(destructuredInitPath), init);
15639
+ }
15640
+ includeDestructuredIfNecessary(context, destructuredInitPath, init) {
15641
+ const path = this.getPathInProperty(destructuredInitPath);
15642
+ let included = this.value.includeDestructuredIfNecessary(context, path, init) ||
15643
+ this.included;
15644
+ if ((included ||= this.key.hasEffects(createHasEffectsContext()))) {
15645
+ this.key.include(context, false);
15646
+ if (!this.value.included) {
15647
+ this.value.included = true;
15648
+ // Unfortunately, we need to include the value again now, so that any
15649
+ // declared variables are properly included.
15650
+ this.value.includeDestructuredIfNecessary(context, path, init);
15651
+ }
15652
+ }
15653
+ return (this.included = included);
15654
+ }
15655
+ include(context, includeChildrenRecursively) {
15656
+ this.included = true;
15657
+ this.key.include(context, includeChildrenRecursively);
15658
+ this.value.include(context, includeChildrenRecursively);
15659
+ }
15660
+ includePath(path, context) {
15661
+ this.included = true;
15662
+ this.value.includePath(path, context);
14923
15663
  }
14924
15664
  markDeclarationReached() {
14925
15665
  this.value.markDeclarationReached();
@@ -14930,14 +15670,20 @@ class Property extends MethodBase {
14930
15670
  }
14931
15671
  this.value.render(code, options, { isShorthandProperty: this.shorthand });
14932
15672
  }
14933
- applyDeoptimizations() {
14934
- this.deoptimized = true;
14935
- if (this.declarationInit !== null) {
14936
- this.declarationInit.deoptimizePath([UnknownKey, UnknownKey]);
14937
- this.scope.context.requestTreeshakingPass();
14938
- }
15673
+ getPathInProperty(destructuredInitPath) {
15674
+ return destructuredInitPath.at(-1) === UnknownKey
15675
+ ? destructuredInitPath
15676
+ : // For now, we only consider static paths as we do not know how to
15677
+ // deoptimize the path in the dynamic case.
15678
+ this.computed
15679
+ ? [...destructuredInitPath, UnknownKey]
15680
+ : this.key instanceof Identifier
15681
+ ? [...destructuredInitPath, this.key.name]
15682
+ : [...destructuredInitPath, String(this.key.value)];
14939
15683
  }
14940
15684
  }
15685
+ Property.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
15686
+ Property.prototype.applyDeoptimizations = doNotDeoptimize;
14941
15687
 
14942
15688
  class PropertyDefinition extends NodeBase {
14943
15689
  get computed() {
@@ -14970,8 +15716,15 @@ class PropertyDefinition extends NodeBase {
14970
15716
  hasEffectsOnInteractionAtPath(path, interaction, context) {
14971
15717
  return !this.value || this.value.hasEffectsOnInteractionAtPath(path, interaction, context);
14972
15718
  }
14973
- applyDeoptimizations() { }
15719
+ includeNode(context) {
15720
+ this.included = true;
15721
+ this.value?.includePath(UNKNOWN_PATH, context);
15722
+ for (const decorator of this.decorators) {
15723
+ decorator.includePath(UNKNOWN_PATH, context);
15724
+ }
15725
+ }
14974
15726
  }
15727
+ PropertyDefinition.prototype.applyDeoptimizations = doNotDeoptimize;
14975
15728
 
14976
15729
  class ReturnStatement extends NodeBase {
14977
15730
  hasEffects(context) {
@@ -14981,10 +15734,15 @@ class ReturnStatement extends NodeBase {
14981
15734
  return false;
14982
15735
  }
14983
15736
  include(context, includeChildrenRecursively) {
14984
- this.included = true;
15737
+ if (!this.included)
15738
+ this.includeNode(context);
14985
15739
  this.argument?.include(context, includeChildrenRecursively);
14986
15740
  context.brokenFlow = true;
14987
15741
  }
15742
+ includeNode(context) {
15743
+ this.included = true;
15744
+ this.argument?.includePath(UNKNOWN_PATH, context);
15745
+ }
14988
15746
  initialise() {
14989
15747
  super.initialise();
14990
15748
  this.scope.addReturnExpression(this.argument || UNKNOWN_EXPRESSION);
@@ -14998,6 +15756,7 @@ class ReturnStatement extends NodeBase {
14998
15756
  }
14999
15757
  }
15000
15758
  }
15759
+ ReturnStatement.prototype.applyDeoptimizations = doNotDeoptimize;
15001
15760
 
15002
15761
  class SequenceExpression extends NodeBase {
15003
15762
  deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
@@ -15025,10 +15784,15 @@ class SequenceExpression extends NodeBase {
15025
15784
  for (const expression of this.expressions) {
15026
15785
  if (includeChildrenRecursively ||
15027
15786
  (expression === lastExpression && !(this.parent instanceof ExpressionStatement)) ||
15028
- expression.shouldBeIncluded(context))
15787
+ expression.shouldBeIncluded(context)) {
15029
15788
  expression.include(context, includeChildrenRecursively);
15789
+ }
15030
15790
  }
15031
15791
  }
15792
+ includePath(path, context) {
15793
+ this.included = true;
15794
+ this.expressions[this.expressions.length - 1].includePath(path, context);
15795
+ }
15032
15796
  removeAnnotations(code) {
15033
15797
  this.expressions[0].removeAnnotations(code);
15034
15798
  }
@@ -15063,6 +15827,8 @@ class SequenceExpression extends NodeBase {
15063
15827
  }
15064
15828
  }
15065
15829
  }
15830
+ SequenceExpression.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
15831
+ SequenceExpression.prototype.applyDeoptimizations = doNotDeoptimize;
15066
15832
 
15067
15833
  class Super extends NodeBase {
15068
15834
  bind() {
@@ -15074,11 +15840,15 @@ class Super extends NodeBase {
15074
15840
  deoptimizePath(path) {
15075
15841
  this.variable.deoptimizePath(path);
15076
15842
  }
15077
- include() {
15078
- if (!this.included) {
15079
- this.included = true;
15080
- this.scope.context.includeVariableInModule(this.variable);
15081
- }
15843
+ include(context) {
15844
+ if (!this.included)
15845
+ this.includeNode(context);
15846
+ }
15847
+ includeNode(context) {
15848
+ this.included = true;
15849
+ if (!this.deoptimized)
15850
+ this.applyDeoptimizations();
15851
+ this.scope.context.includeVariableInModule(this.variable, EMPTY_PATH, context);
15082
15852
  }
15083
15853
  }
15084
15854
 
@@ -15119,6 +15889,8 @@ class SwitchCase extends NodeBase {
15119
15889
  }
15120
15890
  }
15121
15891
  SwitchCase.prototype.needsBoundaries = true;
15892
+ SwitchCase.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
15893
+ SwitchCase.prototype.applyDeoptimizations = doNotDeoptimize;
15122
15894
 
15123
15895
  class SwitchStatement extends NodeBase {
15124
15896
  createScope(parentScope) {
@@ -15201,6 +15973,8 @@ class SwitchStatement extends NodeBase {
15201
15973
  }
15202
15974
  }
15203
15975
  }
15976
+ SwitchStatement.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
15977
+ SwitchStatement.prototype.applyDeoptimizations = doNotDeoptimize;
15204
15978
 
15205
15979
  class TaggedTemplateExpression extends CallExpressionBase {
15206
15980
  bind() {
@@ -15224,8 +15998,8 @@ class TaggedTemplateExpression extends CallExpressionBase {
15224
15998
  this.tag.hasEffectsOnInteractionAtPath(EMPTY_PATH, this.interaction, context));
15225
15999
  }
15226
16000
  include(context, includeChildrenRecursively) {
15227
- if (!this.deoptimized)
15228
- this.applyDeoptimizations();
16001
+ if (!this.included)
16002
+ this.includeNode(context);
15229
16003
  if (includeChildrenRecursively) {
15230
16004
  super.include(context, includeChildrenRecursively);
15231
16005
  }
@@ -15234,7 +16008,7 @@ class TaggedTemplateExpression extends CallExpressionBase {
15234
16008
  this.tag.include(context, includeChildrenRecursively);
15235
16009
  this.quasi.include(context, includeChildrenRecursively);
15236
16010
  }
15237
- this.tag.includeCallArguments(context, this.args);
16011
+ this.tag.includeCallArguments(context, this.interaction);
15238
16012
  const [returnExpression] = this.getReturnExpression();
15239
16013
  if (!returnExpression.included) {
15240
16014
  returnExpression.include(context, false);
@@ -15269,6 +16043,7 @@ class TaggedTemplateExpression extends CallExpressionBase {
15269
16043
  return this.returnExpression;
15270
16044
  }
15271
16045
  }
16046
+ TaggedTemplateExpression.prototype.includeNode = onlyIncludeSelf;
15272
16047
 
15273
16048
  class TemplateElement extends NodeBase {
15274
16049
  get tail() {
@@ -15282,15 +16057,13 @@ class TemplateElement extends NodeBase {
15282
16057
  hasEffects() {
15283
16058
  return false;
15284
16059
  }
15285
- include() {
15286
- this.included = true;
15287
- }
15288
16060
  parseNode(esTreeNode) {
15289
16061
  this.value = esTreeNode.value;
15290
16062
  return super.parseNode(esTreeNode);
15291
16063
  }
15292
16064
  render() { }
15293
16065
  }
16066
+ TemplateElement.prototype.includeNode = onlyIncludeSelf;
15294
16067
 
15295
16068
  class TemplateLiteral extends NodeBase {
15296
16069
  deoptimizeArgumentsOnInteractionAtPath() { }
@@ -15315,6 +16088,14 @@ class TemplateLiteral extends NodeBase {
15315
16088
  }
15316
16089
  return true;
15317
16090
  }
16091
+ includeNode(context) {
16092
+ this.included = true;
16093
+ if (!this.deoptimized)
16094
+ this.applyDeoptimizations();
16095
+ for (const node of this.expressions) {
16096
+ node.includePath(UNKNOWN_PATH, context);
16097
+ }
16098
+ }
15318
16099
  render(code, options) {
15319
16100
  code.indentExclusionRanges.push([this.start, this.end]);
15320
16101
  super.render(code, options);
@@ -15324,13 +16105,13 @@ class TemplateLiteral extends NodeBase {
15324
16105
  class ModuleScope extends ChildScope {
15325
16106
  constructor(parent, context) {
15326
16107
  super(parent, context);
15327
- this.variables.set('this', new LocalVariable('this', null, UNDEFINED_EXPRESSION, context, 'other'));
16108
+ this.variables.set('this', new LocalVariable('this', null, UNDEFINED_EXPRESSION, EMPTY_PATH, context, 'other'));
15328
16109
  }
15329
- addDeclaration(identifier, context, init, kind) {
16110
+ addDeclaration(identifier, context, init, destructuredInitPath, kind) {
15330
16111
  if (this.context.module.importDescriptions.has(identifier.name)) {
15331
16112
  context.error(parseAst_js.logRedeclarationError(identifier.name), identifier.start);
15332
16113
  }
15333
- return super.addDeclaration(identifier, context, init, kind);
16114
+ return super.addDeclaration(identifier, context, init, destructuredInitPath, kind);
15334
16115
  }
15335
16116
  addExportDefaultDeclaration(name, exportDefaultDeclaration, context) {
15336
16117
  const variable = new ExportDefaultVariable(name, exportDefaultDeclaration, context);
@@ -15375,10 +16156,23 @@ class ThisExpression extends NodeBase {
15375
16156
  }
15376
16157
  return this.variable.hasEffectsOnInteractionAtPath(path, interaction, context);
15377
16158
  }
15378
- include() {
16159
+ include(context) {
16160
+ if (!this.included)
16161
+ this.includeNode(context);
16162
+ }
16163
+ includeNode(context) {
16164
+ this.included = true;
16165
+ if (!this.deoptimized)
16166
+ this.applyDeoptimizations();
16167
+ this.scope.context.includeVariableInModule(this.variable, EMPTY_PATH, context);
16168
+ }
16169
+ includePath(path, context) {
15379
16170
  if (!this.included) {
15380
16171
  this.included = true;
15381
- this.scope.context.includeVariableInModule(this.variable);
16172
+ this.scope.context.includeVariableInModule(this.variable, path, context);
16173
+ }
16174
+ else if (path.length > 0) {
16175
+ this.variable.includePath(path, context);
15382
16176
  }
15383
16177
  }
15384
16178
  initialise() {
@@ -15406,7 +16200,8 @@ class ThrowStatement extends NodeBase {
15406
16200
  return true;
15407
16201
  }
15408
16202
  include(context, includeChildrenRecursively) {
15409
- this.included = true;
16203
+ if (!this.included)
16204
+ this.includeNode(context);
15410
16205
  this.argument.include(context, includeChildrenRecursively);
15411
16206
  context.brokenFlow = true;
15412
16207
  }
@@ -15417,6 +16212,7 @@ class ThrowStatement extends NodeBase {
15417
16212
  }
15418
16213
  }
15419
16214
  }
16215
+ ThrowStatement.prototype.includeNode = onlyIncludeSelf;
15420
16216
 
15421
16217
  class TryStatement extends NodeBase {
15422
16218
  constructor() {
@@ -15453,6 +16249,8 @@ class TryStatement extends NodeBase {
15453
16249
  this.finalizer?.include(context, includeChildrenRecursively);
15454
16250
  }
15455
16251
  }
16252
+ TryStatement.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
16253
+ TryStatement.prototype.applyDeoptimizations = doNotDeoptimize;
15456
16254
 
15457
16255
  const unaryOperators = {
15458
16256
  '!': value => !value,
@@ -15559,6 +16357,7 @@ function getSimplifiedNumber(value) {
15559
16357
  const stringifiedValue = String(value).replace('+', '');
15560
16358
  return finalizedExp.length < stringifiedValue.length ? finalizedExp : stringifiedValue;
15561
16359
  }
16360
+ UnaryExpression.prototype.includeNode = onlyIncludeSelf;
15562
16361
 
15563
16362
  class UpdateExpression extends NodeBase {
15564
16363
  hasEffects(context) {
@@ -15570,9 +16369,8 @@ class UpdateExpression extends NodeBase {
15570
16369
  return path.length > 1 || type !== INTERACTION_ACCESSED;
15571
16370
  }
15572
16371
  include(context, includeChildrenRecursively) {
15573
- if (!this.deoptimized)
15574
- this.applyDeoptimizations();
15575
- this.included = true;
16372
+ if (!this.included)
16373
+ this.includeNode(context);
15576
16374
  this.argument.includeAsAssignmentTarget(context, includeChildrenRecursively, true);
15577
16375
  }
15578
16376
  initialise() {
@@ -15611,6 +16409,7 @@ class UpdateExpression extends NodeBase {
15611
16409
  this.scope.context.requestTreeshakingPass();
15612
16410
  }
15613
16411
  }
16412
+ UpdateExpression.prototype.includeNode = onlyIncludeSelf;
15614
16413
 
15615
16414
  function areAllDeclarationsIncludedAndNotExported(declarations, exportNamesByVariable) {
15616
16415
  for (const declarator of declarations) {
@@ -15641,8 +16440,9 @@ class VariableDeclaration extends NodeBase {
15641
16440
  include(context, includeChildrenRecursively, { asSingleStatement } = parseAst_js.BLANK) {
15642
16441
  this.included = true;
15643
16442
  for (const declarator of this.declarations) {
15644
- if (includeChildrenRecursively || declarator.shouldBeIncluded(context))
16443
+ if (includeChildrenRecursively || declarator.shouldBeIncluded(context)) {
15645
16444
  declarator.include(context, includeChildrenRecursively);
16445
+ }
15646
16446
  const { id, init } = declarator;
15647
16447
  if (asSingleStatement) {
15648
16448
  id.include(context, includeChildrenRecursively);
@@ -15680,7 +16480,6 @@ class VariableDeclaration extends NodeBase {
15680
16480
  this.renderReplacedDeclarations(code, options);
15681
16481
  }
15682
16482
  }
15683
- applyDeoptimizations() { }
15684
16483
  renderDeclarationEnd(code, separatorString, lastSeparatorPos, actualContentEnd, renderedContentEnd, systemPatternExports, options) {
15685
16484
  if (code.original.charCodeAt(this.end - 1) === 59 /*";"*/) {
15686
16485
  code.remove(this.end - 1, this.end);
@@ -15723,8 +16522,7 @@ class VariableDeclaration extends NodeBase {
15723
16522
  const singleSystemExport = gatherSystemExportsAndGetSingleExport(separatedNodes, options, aggregatedSystemExports);
15724
16523
  for (const { node, start, separator, contentEnd, end } of separatedNodes) {
15725
16524
  if (!node.included) {
15726
- code.remove(start, end);
15727
- node.removeAnnotations(code);
16525
+ treeshakeNode(node, code, start, end);
15728
16526
  continue;
15729
16527
  }
15730
16528
  node.render(code, options);
@@ -15794,6 +16592,8 @@ function gatherSystemExportsAndGetSingleExport(separatedNodes, options, aggregat
15794
16592
  }
15795
16593
  return singleSystemExport;
15796
16594
  }
16595
+ VariableDeclaration.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
16596
+ VariableDeclaration.prototype.applyDeoptimizations = doNotDeoptimize;
15797
16597
 
15798
16598
  class WhileStatement extends NodeBase {
15799
16599
  hasEffects(context) {
@@ -15807,13 +16607,25 @@ class WhileStatement extends NodeBase {
15807
16607
  includeLoopBody(context, this.body, includeChildrenRecursively);
15808
16608
  }
15809
16609
  }
16610
+ WhileStatement.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
16611
+ WhileStatement.prototype.applyDeoptimizations = doNotDeoptimize;
15810
16612
 
15811
16613
  class YieldExpression extends NodeBase {
16614
+ applyDeoptimizations() {
16615
+ this.deoptimized = true;
16616
+ this.argument?.deoptimizePath(UNKNOWN_PATH);
16617
+ }
15812
16618
  hasEffects(context) {
15813
16619
  if (!this.deoptimized)
15814
16620
  this.applyDeoptimizations();
15815
16621
  return !(context.ignore.returnYield && !this.argument?.hasEffects(context));
15816
16622
  }
16623
+ includeNode(context) {
16624
+ this.included = true;
16625
+ if (!this.deoptimized)
16626
+ this.applyDeoptimizations();
16627
+ this.argument?.includePath(UNKNOWN_PATH, context);
16628
+ }
15817
16629
  render(code, options) {
15818
16630
  if (this.argument) {
15819
16631
  this.argument.render(code, options, { preventASI: true });
@@ -16047,7 +16859,7 @@ const bufferParsers = [
16047
16859
  const annotations = (node.annotations = parseAst_js.convertAnnotations(buffer[position + 1], buffer));
16048
16860
  node.annotationNoSideEffects = annotations.some(comment => comment.type === 'noSideEffects');
16049
16861
  const parameters = (node.params = convertNodeList(node, scope, buffer[position + 2], buffer));
16050
- scope.addParameterVariables(parameters.map(parameter => parameter.declare('parameter', UNKNOWN_EXPRESSION)), parameters[parameters.length - 1] instanceof RestElement);
16862
+ scope.addParameterVariables(parameters.map(parameter => parameter.declare('parameter', EMPTY_PATH, UNKNOWN_EXPRESSION)), parameters[parameters.length - 1] instanceof RestElement);
16051
16863
  node.body = convertNode(node, scope.bodyScope, buffer[position + 3], buffer);
16052
16864
  },
16053
16865
  function assignmentExpression(node, position, buffer) {
@@ -16093,7 +16905,7 @@ const bufferParsers = [
16093
16905
  const parameterPosition = buffer[position];
16094
16906
  const parameter = (node.param =
16095
16907
  parameterPosition === 0 ? null : convertNode(node, scope, parameterPosition, buffer));
16096
- parameter?.declare('parameter', UNKNOWN_EXPRESSION);
16908
+ parameter?.declare('parameter', EMPTY_PATH, UNKNOWN_EXPRESSION);
16097
16909
  node.body = convertNode(node, scope.bodyScope, buffer[position + 1], buffer);
16098
16910
  },
16099
16911
  function chainExpression(node, position, buffer) {
@@ -16231,7 +17043,7 @@ const bufferParsers = [
16231
17043
  node.id =
16232
17044
  idPosition === 0 ? null : convertNode(node, scope.parent, idPosition, buffer);
16233
17045
  const parameters = (node.params = convertNodeList(node, scope, buffer[position + 3], buffer));
16234
- scope.addParameterVariables(parameters.map(parameter => parameter.declare('parameter', UNKNOWN_EXPRESSION)), parameters[parameters.length - 1] instanceof RestElement);
17046
+ scope.addParameterVariables(parameters.map(parameter => parameter.declare('parameter', EMPTY_PATH, UNKNOWN_EXPRESSION)), parameters[parameters.length - 1] instanceof RestElement);
16235
17047
  node.body = convertNode(node, scope.bodyScope, buffer[position + 4], buffer);
16236
17048
  },
16237
17049
  function functionExpression(node, position, buffer) {
@@ -16244,7 +17056,7 @@ const bufferParsers = [
16244
17056
  const idPosition = buffer[position + 2];
16245
17057
  node.id = idPosition === 0 ? null : convertNode(node, node.idScope, idPosition, buffer);
16246
17058
  const parameters = (node.params = convertNodeList(node, scope, buffer[position + 3], buffer));
16247
- scope.addParameterVariables(parameters.map(parameter => parameter.declare('parameter', UNKNOWN_EXPRESSION)), parameters[parameters.length - 1] instanceof RestElement);
17059
+ scope.addParameterVariables(parameters.map(parameter => parameter.declare('parameter', EMPTY_PATH, UNKNOWN_EXPRESSION)), parameters[parameters.length - 1] instanceof RestElement);
16248
17060
  node.body = convertNode(node, scope.bodyScope, buffer[position + 4], buffer);
16249
17061
  },
16250
17062
  function identifier(node, position, buffer) {
@@ -16708,8 +17520,8 @@ class ExportShimVariable extends Variable {
16708
17520
  super(MISSING_EXPORT_SHIM_VARIABLE);
16709
17521
  this.module = module;
16710
17522
  }
16711
- include() {
16712
- super.include();
17523
+ includePath(path, context) {
17524
+ super.includePath(path, context);
16713
17525
  this.module.needsExportShim = true;
16714
17526
  }
16715
17527
  }
@@ -17400,16 +18212,15 @@ class Module {
17400
18212
  markModuleAndImpureDependenciesAsExecuted(this);
17401
18213
  this.graph.needsTreeshakingPass = true;
17402
18214
  }
18215
+ const inclusionContext = createInclusionContext();
17403
18216
  for (const exportName of this.exports.keys()) {
17404
18217
  if (includeNamespaceMembers || exportName !== this.info.syntheticNamedExports) {
17405
18218
  const variable = this.getVariableForExportName(exportName)[0];
17406
18219
  if (!variable) {
17407
18220
  return parseAst_js.error(parseAst_js.logMissingEntryExport(exportName, this.id));
17408
18221
  }
18222
+ this.includeVariable(variable, UNKNOWN_PATH, inclusionContext);
17409
18223
  variable.deoptimizePath(UNKNOWN_PATH);
17410
- if (!variable.included) {
17411
- this.includeVariable(variable);
17412
- }
17413
18224
  }
17414
18225
  }
17415
18226
  for (const name of this.getReexports()) {
@@ -17417,7 +18228,7 @@ class Module {
17417
18228
  if (variable) {
17418
18229
  variable.deoptimizePath(UNKNOWN_PATH);
17419
18230
  if (!variable.included) {
17420
- this.includeVariable(variable);
18231
+ this.includeVariable(variable, UNKNOWN_PATH, inclusionContext);
17421
18232
  }
17422
18233
  if (variable instanceof ExternalVariable) {
17423
18234
  variable.module.reexported = true;
@@ -17438,13 +18249,12 @@ class Module {
17438
18249
  this.graph.needsTreeshakingPass = true;
17439
18250
  }
17440
18251
  let includeNamespaceMembers = false;
18252
+ const inclusionContext = createInclusionContext();
17441
18253
  for (const name of names) {
17442
18254
  const variable = this.getVariableForExportName(name)[0];
17443
18255
  if (variable) {
17444
18256
  variable.deoptimizePath(UNKNOWN_PATH);
17445
- if (!variable.included) {
17446
- this.includeVariable(variable);
17447
- }
18257
+ this.includeVariable(variable, UNKNOWN_PATH, inclusionContext);
17448
18258
  }
17449
18259
  if (!this.exports.has(name) && !this.reexportDescriptions.has(name)) {
17450
18260
  includeNamespaceMembers = true;
@@ -17545,6 +18355,7 @@ class Module {
17545
18355
  manualPureFunctions: this.graph.pureFunctions,
17546
18356
  module: this,
17547
18357
  moduleContext: this.context,
18358
+ newlyIncludedVariableInits: this.graph.newlyIncludedVariableInits,
17548
18359
  options: this.options,
17549
18360
  requestTreeshakingPass: () => (this.graph.needsTreeshakingPass = true),
17550
18361
  traceExport: (name) => this.getVariableForExportName(name)[0],
@@ -17885,13 +18696,13 @@ class Module {
17885
18696
  for (const module of [this, ...this.exportAllModules]) {
17886
18697
  if (module instanceof ExternalModule) {
17887
18698
  const [externalVariable] = module.getVariableForExportName('*');
17888
- externalVariable.include();
18699
+ externalVariable.includePath(UNKNOWN_PATH, createInclusionContext());
17889
18700
  this.includedImports.add(externalVariable);
17890
18701
  externalNamespaces.add(externalVariable);
17891
18702
  }
17892
18703
  else if (module.info.syntheticNamedExports) {
17893
18704
  const syntheticNamespace = module.getSyntheticNamespace();
17894
- syntheticNamespace.include();
18705
+ syntheticNamespace.includePath(UNKNOWN_PATH, createInclusionContext());
17895
18706
  this.includedImports.add(syntheticNamespace);
17896
18707
  syntheticNamespaces.add(syntheticNamespace);
17897
18708
  }
@@ -17901,7 +18712,9 @@ class Module {
17901
18712
  includeDynamicImport(node) {
17902
18713
  const resolution = this.dynamicImports.find(dynamicImport => dynamicImport.node === node).resolution;
17903
18714
  if (resolution instanceof Module) {
17904
- resolution.includedDynamicImporters.push(this);
18715
+ if (!resolution.includedDynamicImporters.includes(this)) {
18716
+ resolution.includedDynamicImporters.push(this);
18717
+ }
17905
18718
  const importedNames = this.options.treeshake
17906
18719
  ? node.getDeterministicImportedNames()
17907
18720
  : undefined;
@@ -17913,15 +18726,15 @@ class Module {
17913
18726
  }
17914
18727
  }
17915
18728
  }
17916
- includeVariable(variable) {
17917
- const variableModule = variable.module;
17918
- if (variable.included) {
18729
+ includeVariable(variable, path, context) {
18730
+ const { included, module: variableModule } = variable;
18731
+ variable.includePath(path, context);
18732
+ if (included) {
17919
18733
  if (variableModule instanceof Module && variableModule !== this) {
17920
18734
  getAndExtendSideEffectModules(variable, this);
17921
18735
  }
17922
18736
  }
17923
18737
  else {
17924
- variable.include();
17925
18738
  this.graph.needsTreeshakingPass = true;
17926
18739
  if (variableModule instanceof Module) {
17927
18740
  if (!variableModule.isExecuted) {
@@ -17938,8 +18751,8 @@ class Module {
17938
18751
  }
17939
18752
  }
17940
18753
  }
17941
- includeVariableInModule(variable) {
17942
- this.includeVariable(variable);
18754
+ includeVariableInModule(variable, path, context) {
18755
+ this.includeVariable(variable, path, context);
17943
18756
  const variableModule = variable.module;
17944
18757
  if (variableModule && variableModule !== this) {
17945
18758
  this.includedImports.add(variable);
@@ -21444,10 +22257,11 @@ class Graph {
21444
22257
  this.options = options;
21445
22258
  this.astLru = flru(5);
21446
22259
  this.cachedModules = new Map();
21447
- this.deoptimizationTracker = new PathTracker();
22260
+ this.deoptimizationTracker = new EntityPathTracker();
21448
22261
  this.entryModules = [];
21449
22262
  this.modulesById = new Map();
21450
22263
  this.needsTreeshakingPass = false;
22264
+ this.newlyIncludedVariableInits = new Set();
21451
22265
  this.phase = BuildPhase.LOAD_AND_PARSE;
21452
22266
  this.scope = new GlobalScope();
21453
22267
  this.watchFiles = Object.create(null);
@@ -21541,6 +22355,7 @@ class Graph {
21541
22355
  }
21542
22356
  if (this.options.treeshake) {
21543
22357
  let treeshakingPass = 1;
22358
+ this.newlyIncludedVariableInits.clear();
21544
22359
  do {
21545
22360
  timeStart(`treeshaking pass ${treeshakingPass}`, 3);
21546
22361
  this.needsTreeshakingPass = false;
@@ -21553,6 +22368,10 @@ class Graph {
21553
22368
  else {
21554
22369
  module.include();
21555
22370
  }
22371
+ for (const entity of this.newlyIncludedVariableInits) {
22372
+ this.newlyIncludedVariableInits.delete(entity);
22373
+ entity.include(createInclusionContext(), false);
22374
+ }
21556
22375
  }
21557
22376
  }
21558
22377
  if (treeshakingPass === 1) {