@rollup/wasm-node 4.28.0 → 4.29.0-0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,22 +1,22 @@
1
1
  /*
2
2
  @license
3
- Rollup.js v4.28.0
4
- Sat, 30 Nov 2024 13:15:17 GMT - commit 0595e433edec3608bfc0331d8f02912374e7f7f7
3
+ Rollup.js v4.29.0-0
4
+ Mon, 16 Dec 2024 06:39:21 GMT - commit 879d03d68890f365f880e30c69b58377b8743407
5
5
 
6
6
  https://github.com/rollup/rollup
7
7
 
8
8
  Released under the MIT License.
9
9
  */
10
- import { ExportDefaultDeclaration as ExportDefaultDeclaration$1, CallExpression as CallExpression$1, EMPTY_ARRAY, LOGLEVEL_WARN, logUnusedExternalImports, ANNOTATION_KEY, INVALID_ANNOTATION_KEY, ObjectExpression as ObjectExpression$1, Property as Property$1, Program as Program$1, logIllegalImportReassignment, BLANK, logRedeclarationError, StaticBlock as StaticBlock$1, CatchClause as CatchClause$1, logDuplicateArgumentNameError, logModuleLevelDirective, ReturnStatement as ReturnStatement$1, VariableDeclarator as VariableDeclarator$1, ExpressionStatement as ExpressionStatement$1, logMissingExport, normalize, getImportPath, logMissingNodeBuiltins, logReservedNamespace, error, logIllegalIdentifierAsName, logMissingNameOptionForIifeExport, logMissingNameOptionForUmdExport, logConstVariableReassignError, ArrowFunctionExpression as ArrowFunctionExpression$1, EMPTY_SET, logCannotCallNamespace, logEval, BlockStatement as BlockStatement$1, getRollupError, logParseError, logModuleParseError, LOGLEVEL_INFO, logFirstSideEffect, locate, logInvalidAnnotation, Identifier as Identifier$1, logThisIsUndefined, getAstBuffer, convertAnnotations, FIXED_STRINGS, convertNode as convertNode$1, EMPTY_OBJECT, logImportAttributeIsInvalid, logImportOptionsAreInvalid, logSyntheticNamedExportsNeedNamespaceExport, logMissingEntryExport, logDuplicateExportError, logInvalidSourcemapForError, augmentCodeLocation, logInconsistentImportAttributes, logMissingJsxExport, logNamespaceConflict, logAmbiguousExternalNamespaces, logShimmedExport, parseAst, logCircularReexport, logInvalidFormatForTopLevelAwait, TemplateLiteral as TemplateLiteral$1, Literal as Literal$1, logAddonNotGenerated, logIncompatibleExportOptionValue, logMixedExport, logFailedValidation, isPathFragment, logCyclicCrossChunkReexport, getAliasName, logUnexpectedNamedImport, isAbsolute as isAbsolute$1, relative as relative$1, logUnexpectedNamespaceReexport, logEmptyChunk, logMissingGlobalName, logOptimizeChunkStatus, logSourcemapBroken, logConflictingSourcemapSources, logChunkInvalid, logInvalidOption, URL_OUTPUT_FORMAT, URL_OUTPUT_DIR, URL_OUTPUT_SOURCEMAPFILE, URL_OUTPUT_AMD_ID, logCannotAssignModuleToChunk, logAnonymousPluginCache, logDuplicatePluginName, logUnknownOption, printQuotedStringList, LOGLEVEL_ERROR, logLevelPriority, LOGLEVEL_DEBUG, logInvalidSetAssetSourceCall, logPluginError, logNoTransformMapOrAstWithoutCode, relativeId, logBadLoader, logExternalModulesCannotBeTransformedToModules, logInternalIdCannotBeExternal, isRelative, logUnresolvedImport, logUnresolvedImportTreatedAsExternal, logExternalSyntheticExports, logUnresolvedEntry, logUnresolvedImplicitDependant, logExternalModulesCannotBeIncludedInManualChunks, logEntryCannotBeExternal, logImplicitDependantCannotBeExternal, logNoAssetSourceSet, logFileReferenceIdNotFoundForFilename, logAssetReferenceIdNotFoundForSetSource, logAssetSourceAlreadySet, logInvalidRollupPhaseForChunkEmission, warnDeprecation, URL_GENERATEBUNDLE, logFileNameConflict, logAssetNotFinalisedForFileName, logChunkNotGeneratedForFileName, logInvalidLogPosition, logInputHookInOutputPlugin, logInvalidFunctionPluginHook, logInvalidAddonPluginHook, logImplicitDependantIsNotIncluded, logCircularDependency, augmentLogMessage, URL_JSX, URL_TREESHAKE, URL_TREESHAKE_MODULESIDEEFFECTS, logInvalidExportOptionValue, URL_OUTPUT_INTEROP, isValidUrl, addTrailingSlashIfMissed, URL_OUTPUT_SOURCEMAPBASEURL, URL_OUTPUT_INLINEDYNAMICIMPORTS, URL_PRESERVEENTRYSIGNATURES, URL_OUTPUT_AMD_BASEPATH, URL_OUTPUT_GENERATEDCODE, URL_OUTPUT_MANUALCHUNKS, URL_OUTPUT_EXTERNALIMPORTATTRIBUTES, logAlreadyClosed, logMissingFileOrDirOption, logCannotEmitFromOptionsHook, URL_WATCH } from './parseAst.js';
10
+ import { EMPTY_OBJECT, ExportDefaultDeclaration as ExportDefaultDeclaration$1, CallExpression as CallExpression$1, EMPTY_ARRAY, LOGLEVEL_WARN, logUnusedExternalImports, ANNOTATION_KEY, INVALID_ANNOTATION_KEY, ObjectExpression as ObjectExpression$1, Property as Property$1, Program as Program$1, logIllegalImportReassignment, BLANK, logRedeclarationError, StaticBlock as StaticBlock$1, CatchClause as CatchClause$1, logDuplicateArgumentNameError, logModuleLevelDirective, ReturnStatement as ReturnStatement$1, VariableDeclarator as VariableDeclarator$1, ExpressionStatement as ExpressionStatement$1, logMissingExport, normalize, getImportPath, logMissingNodeBuiltins, logReservedNamespace, error, logIllegalIdentifierAsName, logMissingNameOptionForIifeExport, logMissingNameOptionForUmdExport, logConstVariableReassignError, ArrowFunctionExpression as ArrowFunctionExpression$1, EMPTY_SET, logCannotCallNamespace, logEval, BlockStatement as BlockStatement$1, getRollupError, logModuleParseError, logParseError, LOGLEVEL_INFO, logFirstSideEffect, locate, logInvalidAnnotation, Identifier as Identifier$1, logThisIsUndefined, getAstBuffer, convertAnnotations, FIXED_STRINGS, convertNode as convertNode$1, logImportAttributeIsInvalid, logImportOptionsAreInvalid, logSyntheticNamedExportsNeedNamespaceExport, logMissingEntryExport, logDuplicateExportError, logInvalidSourcemapForError, augmentCodeLocation, logInconsistentImportAttributes, logMissingJsxExport, logNamespaceConflict, logAmbiguousExternalNamespaces, logShimmedExport, parseAst, logInvalidFormatForTopLevelAwait, TemplateLiteral as TemplateLiteral$1, Literal as Literal$1, logCircularReexport, logAddonNotGenerated, logIncompatibleExportOptionValue, logMixedExport, logFailedValidation, isPathFragment, logCyclicCrossChunkReexport, getAliasName, logUnexpectedNamedImport, isAbsolute as isAbsolute$1, relative as relative$1, logUnexpectedNamespaceReexport, logEmptyChunk, logMissingGlobalName, logOptimizeChunkStatus, logSourcemapBroken, logConflictingSourcemapSources, logChunkInvalid, logInvalidOption, logCannotAssignModuleToChunk, URL_OUTPUT_FORMAT, URL_OUTPUT_DIR, URL_OUTPUT_SOURCEMAPFILE, URL_OUTPUT_AMD_ID, logAnonymousPluginCache, logDuplicatePluginName, logUnknownOption, LOGLEVEL_ERROR, logLevelPriority, LOGLEVEL_DEBUG, printQuotedStringList, logInvalidSetAssetSourceCall, logPluginError, logNoTransformMapOrAstWithoutCode, relativeId, logBadLoader, logExternalModulesCannotBeTransformedToModules, logInternalIdCannotBeExternal, isRelative, logUnresolvedImport, logUnresolvedImportTreatedAsExternal, logExternalSyntheticExports, logUnresolvedEntry, logUnresolvedImplicitDependant, logExternalModulesCannotBeIncludedInManualChunks, logEntryCannotBeExternal, logImplicitDependantCannotBeExternal, logNoAssetSourceSet, logFileReferenceIdNotFoundForFilename, logAssetReferenceIdNotFoundForSetSource, logAssetSourceAlreadySet, logInvalidRollupPhaseForChunkEmission, warnDeprecation, logChunkNotGeneratedForFileName, logAssetNotFinalisedForFileName, logFileNameConflict, URL_GENERATEBUNDLE, logInvalidLogPosition, logInputHookInOutputPlugin, logInvalidAddonPluginHook, logInvalidFunctionPluginHook, logImplicitDependantIsNotIncluded, logCircularDependency, augmentLogMessage, URL_TREESHAKE, URL_JSX, URL_TREESHAKE_MODULESIDEEFFECTS, URL_OUTPUT_INLINEDYNAMICIMPORTS, URL_PRESERVEENTRYSIGNATURES, URL_OUTPUT_GENERATEDCODE, isValidUrl, addTrailingSlashIfMissed, URL_OUTPUT_SOURCEMAPBASEURL, URL_OUTPUT_MANUALCHUNKS, logInvalidExportOptionValue, URL_OUTPUT_AMD_BASEPATH, URL_OUTPUT_INTEROP, URL_OUTPUT_EXTERNALIMPORTATTRIBUTES, logAlreadyClosed, logMissingFileOrDirOption, logCannotEmitFromOptionsHook, URL_WATCH } from './parseAst.js';
11
11
  import { relative, dirname, basename, extname, resolve as resolve$1 } from 'node:path';
12
- import { posix, win32, isAbsolute, resolve } from 'path';
13
- import { parseAsync, xxhashBase64Url, xxhashBase36, xxhashBase16 } from '../../native.js';
12
+ import { posix, isAbsolute, resolve, win32 } from 'path';
13
+ import { parseAsync, xxhashBase16, xxhashBase64Url, xxhashBase36 } from '../../native.js';
14
14
  import process$1, { env as env$1 } from 'node:process';
15
15
  import { performance } from 'node:perf_hooks';
16
16
  import { lstat, realpath, readdir, readFile, mkdir, writeFile } from 'node:fs/promises';
17
17
  import * as tty from 'tty';
18
18
 
19
- var version = "4.28.0";
19
+ var version = "4.29.0-0";
20
20
 
21
21
  const comma = ','.charCodeAt(0);
22
22
  const semicolon = ';'.charCodeAt(0);
@@ -1948,71 +1948,6 @@ function renderSystemExportSequenceBeforeExpression(exportedVariable, expression
1948
1948
  }
1949
1949
  }
1950
1950
 
1951
- /** @import { Node } from 'estree' */
1952
-
1953
- /**
1954
- * @param {Node} node
1955
- * @param {Node} parent
1956
- * @returns {boolean}
1957
- */
1958
- function is_reference(node, parent) {
1959
- if (node.type === 'MemberExpression') {
1960
- return !node.computed && is_reference(node.object, node);
1961
- }
1962
-
1963
- if (node.type !== 'Identifier') return false;
1964
-
1965
- switch (parent?.type) {
1966
- // disregard `bar` in `foo.bar`
1967
- case 'MemberExpression':
1968
- return parent.computed || node === parent.object;
1969
-
1970
- // disregard the `foo` in `class {foo(){}}` but keep it in `class {[foo](){}}`
1971
- case 'MethodDefinition':
1972
- return parent.computed;
1973
-
1974
- // disregard the `meta` in `import.meta`
1975
- case 'MetaProperty':
1976
- return parent.meta === node;
1977
-
1978
- // disregard the `foo` in `class {foo=bar}` but keep it in `class {[foo]=bar}` and `class {bar=foo}`
1979
- case 'PropertyDefinition':
1980
- return parent.computed || node === parent.value;
1981
-
1982
- // disregard the `bar` in `{ bar: foo }`, but keep it in `{ [bar]: foo }`
1983
- case 'Property':
1984
- return parent.computed || node === parent.value;
1985
-
1986
- // disregard the `bar` in `export { foo as bar }` or
1987
- // the foo in `import { foo as bar }`
1988
- case 'ExportSpecifier':
1989
- case 'ImportSpecifier':
1990
- return node === parent.local;
1991
-
1992
- // disregard the `foo` in `foo: while (...) { ... break foo; ... continue foo;}`
1993
- case 'LabeledStatement':
1994
- case 'BreakStatement':
1995
- case 'ContinueStatement':
1996
- return false;
1997
-
1998
- default:
1999
- return true;
2000
- }
2001
- }
2002
-
2003
- const PureFunctionKey = Symbol('PureFunction');
2004
- const getPureFunctions = ({ treeshake }) => {
2005
- const pureFunctions = Object.create(null);
2006
- for (const functionName of treeshake ? treeshake.manualPureFunctions : []) {
2007
- let currentFunctions = pureFunctions;
2008
- for (const pathSegment of functionName.split('.')) {
2009
- currentFunctions = currentFunctions[pathSegment] ||= Object.create(null);
2010
- }
2011
- currentFunctions[PureFunctionKey] = true;
2012
- }
2013
- return pureFunctions;
2014
- };
2015
-
2016
1951
  function getOrCreate(map, key, init) {
2017
1952
  const existing = map.get(key);
2018
1953
  if (existing !== undefined) {
@@ -2043,7 +1978,7 @@ const UNKNOWN_PATH = [UnknownKey];
2043
1978
  const UNKNOWN_NON_ACCESSOR_PATH = [UnknownNonAccessorKey];
2044
1979
  const UNKNOWN_INTEGER_PATH = [UnknownInteger];
2045
1980
  const EntitiesKey = Symbol('Entities');
2046
- class PathTracker {
1981
+ class EntityPathTracker {
2047
1982
  constructor() {
2048
1983
  this.entityPaths = Object.create(null, {
2049
1984
  [EntitiesKey]: { value: new Set() }
@@ -2068,14 +2003,14 @@ class PathTracker {
2068
2003
  getEntities(path) {
2069
2004
  let currentPaths = this.entityPaths;
2070
2005
  for (const pathSegment of path) {
2071
- currentPaths = currentPaths[pathSegment] =
2072
- currentPaths[pathSegment] ||
2073
- Object.create(null, { [EntitiesKey]: { value: new Set() } });
2006
+ currentPaths = currentPaths[pathSegment] ||= Object.create(null, {
2007
+ [EntitiesKey]: { value: new Set() }
2008
+ });
2074
2009
  }
2075
2010
  return currentPaths[EntitiesKey];
2076
2011
  }
2077
2012
  }
2078
- const SHARED_RECURSION_TRACKER = new PathTracker();
2013
+ const SHARED_RECURSION_TRACKER = new EntityPathTracker();
2079
2014
  class DiscriminatedPathTracker {
2080
2015
  constructor() {
2081
2016
  this.entityPaths = Object.create(null, {
@@ -2085,9 +2020,9 @@ class DiscriminatedPathTracker {
2085
2020
  trackEntityAtPathAndGetIfTracked(path, discriminator, entity) {
2086
2021
  let currentPaths = this.entityPaths;
2087
2022
  for (const pathSegment of path) {
2088
- currentPaths = currentPaths[pathSegment] =
2089
- currentPaths[pathSegment] ||
2090
- Object.create(null, { [EntitiesKey]: { value: new Map() } });
2023
+ currentPaths = currentPaths[pathSegment] ||= Object.create(null, {
2024
+ [EntitiesKey]: { value: new Map() }
2025
+ });
2091
2026
  }
2092
2027
  const trackedEntities = getOrCreate(currentPaths[EntitiesKey], discriminator, (getNewSet));
2093
2028
  if (trackedEntities.has(entity))
@@ -2096,6 +2031,137 @@ class DiscriminatedPathTracker {
2096
2031
  return false;
2097
2032
  }
2098
2033
  }
2034
+ const UNKNOWN_INCLUDED_PATH = Object.freeze({ [UnknownKey]: EMPTY_OBJECT });
2035
+ class IncludedPathTracker {
2036
+ constructor() {
2037
+ this.includedPaths = null;
2038
+ }
2039
+ includePathAndGetIfIncluded(path) {
2040
+ let included = true;
2041
+ let parent = this;
2042
+ let parentSegment = 'includedPaths';
2043
+ let currentPaths = (this.includedPaths ||=
2044
+ ((included = false), Object.create(null)));
2045
+ for (const pathSegment of path) {
2046
+ // This means from here, all paths are included
2047
+ if (currentPaths[UnknownKey]) {
2048
+ return true;
2049
+ }
2050
+ // Including UnknownKey automatically includes all nested paths.
2051
+ // From above, we know that UnknownKey is not included yet.
2052
+ if (typeof pathSegment === 'symbol') {
2053
+ // Hopefully, this saves some memory over just setting
2054
+ // currentPaths[UnknownKey] = EMPTY_OBJECT
2055
+ parent[parentSegment] = UNKNOWN_INCLUDED_PATH;
2056
+ return false;
2057
+ }
2058
+ parent = currentPaths;
2059
+ parentSegment = pathSegment;
2060
+ currentPaths = currentPaths[pathSegment] ||= ((included = false), Object.create(null));
2061
+ }
2062
+ return included;
2063
+ }
2064
+ includeAllPaths(entity, context, basePath) {
2065
+ const { includedPaths } = this;
2066
+ if (includedPaths) {
2067
+ includeAllPaths(entity, context, basePath, includedPaths);
2068
+ }
2069
+ }
2070
+ }
2071
+ function includeAllPaths(entity, context, basePath, currentPaths) {
2072
+ if (currentPaths[UnknownKey]) {
2073
+ return entity.includePath([...basePath, UnknownKey], context);
2074
+ }
2075
+ const keys = Object.keys(currentPaths);
2076
+ if (keys.length === 0) {
2077
+ return entity.includePath(basePath, context);
2078
+ }
2079
+ for (const key of keys) {
2080
+ includeAllPaths(entity, context, [...basePath, key], currentPaths[key]);
2081
+ }
2082
+ }
2083
+
2084
+ /** @import { Node } from 'estree' */
2085
+
2086
+ /**
2087
+ * @param {Node} node
2088
+ * @param {Node} parent
2089
+ * @returns {boolean}
2090
+ */
2091
+ function is_reference(node, parent) {
2092
+ if (node.type === 'MemberExpression') {
2093
+ return !node.computed && is_reference(node.object, node);
2094
+ }
2095
+
2096
+ if (node.type !== 'Identifier') return false;
2097
+
2098
+ switch (parent?.type) {
2099
+ // disregard `bar` in `foo.bar`
2100
+ case 'MemberExpression':
2101
+ return parent.computed || node === parent.object;
2102
+
2103
+ // disregard the `foo` in `class {foo(){}}` but keep it in `class {[foo](){}}`
2104
+ case 'MethodDefinition':
2105
+ return parent.computed;
2106
+
2107
+ // disregard the `meta` in `import.meta`
2108
+ case 'MetaProperty':
2109
+ return parent.meta === node;
2110
+
2111
+ // disregard the `foo` in `class {foo=bar}` but keep it in `class {[foo]=bar}` and `class {bar=foo}`
2112
+ case 'PropertyDefinition':
2113
+ return parent.computed || node === parent.value;
2114
+
2115
+ // disregard the `bar` in `{ bar: foo }`, but keep it in `{ [bar]: foo }`
2116
+ case 'Property':
2117
+ return parent.computed || node === parent.value;
2118
+
2119
+ // disregard the `bar` in `export { foo as bar }` or
2120
+ // the foo in `import { foo as bar }`
2121
+ case 'ExportSpecifier':
2122
+ case 'ImportSpecifier':
2123
+ return node === parent.local;
2124
+
2125
+ // disregard the `foo` in `foo: while (...) { ... break foo; ... continue foo;}`
2126
+ case 'LabeledStatement':
2127
+ case 'BreakStatement':
2128
+ case 'ContinueStatement':
2129
+ return false;
2130
+
2131
+ default:
2132
+ return true;
2133
+ }
2134
+ }
2135
+
2136
+ function createInclusionContext() {
2137
+ return {
2138
+ brokenFlow: false,
2139
+ hasBreak: false,
2140
+ hasContinue: false,
2141
+ includedCallArguments: new Set(),
2142
+ includedLabels: new Set()
2143
+ };
2144
+ }
2145
+ function createHasEffectsContext() {
2146
+ return {
2147
+ accessed: new EntityPathTracker(),
2148
+ assigned: new EntityPathTracker(),
2149
+ brokenFlow: false,
2150
+ called: new DiscriminatedPathTracker(),
2151
+ hasBreak: false,
2152
+ hasContinue: false,
2153
+ ignore: {
2154
+ breaks: false,
2155
+ continues: false,
2156
+ labels: new Set(),
2157
+ returnYield: false,
2158
+ this: false
2159
+ },
2160
+ includedLabels: new Set(),
2161
+ instantiated: new DiscriminatedPathTracker(),
2162
+ replacedVariableInits: new Map()
2163
+ };
2164
+ }
2099
2165
 
2100
2166
  function isFlagSet(flags, flag) {
2101
2167
  return (flags & flag) !== 0;
@@ -2134,12 +2200,25 @@ class ExpressionEntity {
2134
2200
  hasEffectsOnInteractionAtPath(_path, _interaction, _context) {
2135
2201
  return true;
2136
2202
  }
2137
- include(_context, _includeChildrenRecursively, _options) {
2203
+ include(context, _includeChildrenRecursively, _options) {
2204
+ if (!this.included)
2205
+ this.includeNode(context);
2206
+ }
2207
+ includeNode(_context) {
2138
2208
  this.included = true;
2139
2209
  }
2140
- includeCallArguments(context, parameters) {
2141
- for (const argument of parameters) {
2142
- argument.include(context, false);
2210
+ includePath(_path, context) {
2211
+ if (!this.included)
2212
+ this.includeNode(context);
2213
+ }
2214
+ /* We are both including and including an unknown path here as the former
2215
+ * ensures that nested nodes are included while the latter ensures that all
2216
+ * paths of the expression are included.
2217
+ * */
2218
+ includeCallArguments(context, interaction) {
2219
+ for (const argument of interaction.args) {
2220
+ argument?.includePath(UNKNOWN_PATH, context);
2221
+ argument?.include(context, false);
2143
2222
  }
2144
2223
  }
2145
2224
  shouldBeIncluded(_context) {
@@ -2178,6 +2257,19 @@ const NODE_INTERACTION_UNKNOWN_CALL = {
2178
2257
  withNew: false
2179
2258
  };
2180
2259
 
2260
+ const PureFunctionKey = Symbol('PureFunction');
2261
+ const getPureFunctions = ({ treeshake }) => {
2262
+ const pureFunctions = Object.create(null);
2263
+ for (const functionName of treeshake ? treeshake.manualPureFunctions : []) {
2264
+ let currentFunctions = pureFunctions;
2265
+ for (const pathSegment of functionName.split('.')) {
2266
+ currentFunctions = currentFunctions[pathSegment] ||= Object.create(null);
2267
+ }
2268
+ currentFunctions[PureFunctionKey] = true;
2269
+ }
2270
+ return pureFunctions;
2271
+ };
2272
+
2181
2273
  class Variable extends ExpressionEntity {
2182
2274
  markReassigned() {
2183
2275
  this.isReassigned = true;
@@ -2254,9 +2346,9 @@ class Variable extends ExpressionEntity {
2254
2346
  * has not been included previously. Once a variable is included, it should
2255
2347
  * take care all its declarations are included.
2256
2348
  */
2257
- include() {
2349
+ includePath(path, context) {
2258
2350
  this.included = true;
2259
- this.renderedLikeHoisted?.include();
2351
+ this.renderedLikeHoisted?.includePath(path, context);
2260
2352
  }
2261
2353
  /**
2262
2354
  * Links the rendered name of this variable to another variable and includes
@@ -2288,8 +2380,8 @@ class ExternalVariable extends Variable {
2288
2380
  hasEffectsOnInteractionAtPath(path, { type }) {
2289
2381
  return type !== INTERACTION_ACCESSED || path.length > (this.isNamespace ? 1 : 0);
2290
2382
  }
2291
- include() {
2292
- super.include();
2383
+ includePath(path, context) {
2384
+ super.includePath(path, context);
2293
2385
  this.module.used = true;
2294
2386
  }
2295
2387
  }
@@ -2590,36 +2682,6 @@ const childNodeKeys = {
2590
2682
  YieldExpression: ['argument']
2591
2683
  };
2592
2684
 
2593
- function createInclusionContext() {
2594
- return {
2595
- brokenFlow: false,
2596
- hasBreak: false,
2597
- hasContinue: false,
2598
- includedCallArguments: new Set(),
2599
- includedLabels: new Set()
2600
- };
2601
- }
2602
- function createHasEffectsContext() {
2603
- return {
2604
- accessed: new PathTracker(),
2605
- assigned: new PathTracker(),
2606
- brokenFlow: false,
2607
- called: new DiscriminatedPathTracker(),
2608
- hasBreak: false,
2609
- hasContinue: false,
2610
- ignore: {
2611
- breaks: false,
2612
- continues: false,
2613
- labels: new Set(),
2614
- returnYield: false,
2615
- this: false
2616
- },
2617
- includedLabels: new Set(),
2618
- instantiated: new DiscriminatedPathTracker(),
2619
- replacedVariableInits: new Map()
2620
- };
2621
- }
2622
-
2623
2685
  const INCLUDE_PARAMETERS = 'variables';
2624
2686
  const IS_SKIPPED_CHAIN = Symbol('IS_SKIPPED_CHAIN');
2625
2687
  class NodeBase extends ExpressionEntity {
@@ -2689,9 +2751,8 @@ class NodeBase extends ExpressionEntity {
2689
2751
  this.hasEffectsOnInteractionAtPath(EMPTY_PATH, this.assignmentInteraction, context));
2690
2752
  }
2691
2753
  include(context, includeChildrenRecursively, _options) {
2692
- if (!this.deoptimized)
2693
- this.applyDeoptimizations();
2694
- this.included = true;
2754
+ if (!this.included)
2755
+ this.includeNode(context);
2695
2756
  for (const key of childNodeKeys[this.type]) {
2696
2757
  const value = this[key];
2697
2758
  if (value === null)
@@ -2706,6 +2767,24 @@ class NodeBase extends ExpressionEntity {
2706
2767
  }
2707
2768
  }
2708
2769
  }
2770
+ includeNode(context) {
2771
+ this.included = true;
2772
+ if (!this.deoptimized)
2773
+ this.applyDeoptimizations();
2774
+ for (const key of childNodeKeys[this.type]) {
2775
+ const value = this[key];
2776
+ if (value === null)
2777
+ continue;
2778
+ if (Array.isArray(value)) {
2779
+ for (const child of value) {
2780
+ child?.includePath(UNKNOWN_PATH, context);
2781
+ }
2782
+ }
2783
+ else {
2784
+ value.includePath(UNKNOWN_PATH, context);
2785
+ }
2786
+ }
2787
+ }
2709
2788
  includeAsAssignmentTarget(context, includeChildrenRecursively, _deoptimizeAccess) {
2710
2789
  this.include(context, includeChildrenRecursively);
2711
2790
  }
@@ -2809,6 +2888,17 @@ class NodeBase extends ExpressionEntity {
2809
2888
  function createChildNodeKeysForNode(esTreeNode) {
2810
2889
  return Object.keys(esTreeNode).filter(key => typeof esTreeNode[key] === 'object' && key.charCodeAt(0) !== 95 /* _ */);
2811
2890
  }
2891
+ function onlyIncludeSelf() {
2892
+ this.included = true;
2893
+ if (!this.deoptimized)
2894
+ this.applyDeoptimizations();
2895
+ }
2896
+ function onlyIncludeSelfNoDeoptimize() {
2897
+ this.included = true;
2898
+ }
2899
+ function doNotDeoptimize() {
2900
+ this.deoptimized = true;
2901
+ }
2812
2902
 
2813
2903
  function isObjectExpressionNode(node) {
2814
2904
  return node instanceof NodeBase && node.type === ObjectExpression$1;
@@ -2821,8 +2911,8 @@ function assembleMemberDescriptions(memberDescriptions, inheritedDescriptions =
2821
2911
  return Object.create(inheritedDescriptions, memberDescriptions);
2822
2912
  }
2823
2913
  const UNDEFINED_EXPRESSION = new (class UndefinedExpression extends ExpressionEntity {
2824
- getLiteralValueAtPath() {
2825
- return undefined;
2914
+ getLiteralValueAtPath(path) {
2915
+ return path.length > 0 ? UnknownValue : undefined;
2826
2916
  }
2827
2917
  })();
2828
2918
  const returnsUnknown = {
@@ -3019,31 +3109,6 @@ function getMemberReturnExpressionWhenCalled(members, memberName) {
3019
3109
  return [members[memberName].returns, false];
3020
3110
  }
3021
3111
 
3022
- class SpreadElement extends NodeBase {
3023
- deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
3024
- if (path.length > 0) {
3025
- this.argument.deoptimizeArgumentsOnInteractionAtPath(interaction, UNKNOWN_PATH, recursionTracker);
3026
- }
3027
- }
3028
- hasEffects(context) {
3029
- if (!this.deoptimized)
3030
- this.applyDeoptimizations();
3031
- const { propertyReadSideEffects } = this.scope.context.options
3032
- .treeshake;
3033
- return (this.argument.hasEffects(context) ||
3034
- (propertyReadSideEffects &&
3035
- (propertyReadSideEffects === 'always' ||
3036
- this.argument.hasEffectsOnInteractionAtPath(UNKNOWN_PATH, NODE_INTERACTION_UNKNOWN_ACCESS, context))));
3037
- }
3038
- applyDeoptimizations() {
3039
- this.deoptimized = true;
3040
- // Only properties of properties of the argument could become subject to reassignment
3041
- // This will also reassign the return values of iterators
3042
- this.argument.deoptimizePath([UnknownKey, UnknownKey]);
3043
- this.scope.context.requestTreeshakingPass();
3044
- }
3045
- }
3046
-
3047
3112
  class Method extends ExpressionEntity {
3048
3113
  constructor(description) {
3049
3114
  super();
@@ -3169,6 +3234,7 @@ class ObjectEntity extends ExpressionEntity {
3169
3234
  this.unknownIntegerProps = [];
3170
3235
  this.unmatchableGetters = [];
3171
3236
  this.unmatchablePropertiesAndGetters = [];
3237
+ this.unmatchablePropertiesAndSetters = [];
3172
3238
  this.unmatchableSetters = [];
3173
3239
  if (Array.isArray(properties)) {
3174
3240
  this.buildPropertyMaps(properties);
@@ -3403,9 +3469,38 @@ class ObjectEntity extends ExpressionEntity {
3403
3469
  }
3404
3470
  return false;
3405
3471
  }
3472
+ include(context, includeChildrenRecursively) {
3473
+ this.included = true;
3474
+ for (const property of this.allProperties) {
3475
+ if (includeChildrenRecursively || property.shouldBeIncluded(context)) {
3476
+ property.include(context, includeChildrenRecursively);
3477
+ }
3478
+ }
3479
+ this.prototypeExpression?.include(context, includeChildrenRecursively);
3480
+ }
3481
+ includePath(path, context) {
3482
+ this.included = true;
3483
+ if (path.length === 0)
3484
+ return;
3485
+ const [key, ...subPath] = path;
3486
+ const [includedMembers, includedPath] = typeof key === 'string'
3487
+ ? [
3488
+ [
3489
+ ...new Set([
3490
+ ...(this.propertiesAndGettersByKey[key] || this.unmatchablePropertiesAndGetters),
3491
+ ...(this.propertiesAndSettersByKey[key] || this.unmatchablePropertiesAndSetters)
3492
+ ])
3493
+ ],
3494
+ subPath
3495
+ ]
3496
+ : [this.allProperties, UNKNOWN_PATH];
3497
+ for (const property of includedMembers) {
3498
+ property.includePath(includedPath, context);
3499
+ }
3500
+ this.prototypeExpression?.includePath(path, context);
3501
+ }
3406
3502
  buildPropertyMaps(properties) {
3407
- const { allProperties, propertiesAndGettersByKey, propertiesAndSettersByKey, settersByKey, gettersByKey, unknownIntegerProps, unmatchablePropertiesAndGetters, unmatchableGetters, unmatchableSetters } = this;
3408
- const unmatchablePropertiesAndSetters = [];
3503
+ const { allProperties, propertiesAndGettersByKey, propertiesAndSettersByKey, settersByKey, gettersByKey, unknownIntegerProps, unmatchablePropertiesAndGetters, unmatchablePropertiesAndSetters, unmatchableGetters, unmatchableSetters } = this;
3409
3504
  for (let index = properties.length - 1; index >= 0; index--) {
3410
3505
  const { key, kind, property } = properties[index];
3411
3506
  allProperties.push(property);
@@ -3675,6 +3770,37 @@ const ARRAY_PROTOTYPE = new ObjectEntity({
3675
3770
  values: METHOD_DEOPTS_SELF_RETURNS_UNKNOWN
3676
3771
  }, OBJECT_PROTOTYPE, true);
3677
3772
 
3773
+ class SpreadElement extends NodeBase {
3774
+ deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
3775
+ if (path.length > 0) {
3776
+ this.argument.deoptimizeArgumentsOnInteractionAtPath(interaction, UNKNOWN_PATH, recursionTracker);
3777
+ }
3778
+ }
3779
+ hasEffects(context) {
3780
+ if (!this.deoptimized)
3781
+ this.applyDeoptimizations();
3782
+ const { propertyReadSideEffects } = this.scope.context.options
3783
+ .treeshake;
3784
+ return (this.argument.hasEffects(context) ||
3785
+ (propertyReadSideEffects &&
3786
+ (propertyReadSideEffects === 'always' ||
3787
+ this.argument.hasEffectsOnInteractionAtPath(UNKNOWN_PATH, NODE_INTERACTION_UNKNOWN_ACCESS, context))));
3788
+ }
3789
+ includeNode(context) {
3790
+ this.included = true;
3791
+ if (!this.deoptimized)
3792
+ this.applyDeoptimizations();
3793
+ this.argument.includePath(UNKNOWN_PATH, context);
3794
+ }
3795
+ applyDeoptimizations() {
3796
+ this.deoptimized = true;
3797
+ // Only properties of properties of the argument could become subject to reassignment
3798
+ // This will also reassign the return values of iterators
3799
+ this.argument.deoptimizePath([UnknownKey, UnknownKey]);
3800
+ this.scope.context.requestTreeshakingPass();
3801
+ }
3802
+ }
3803
+
3678
3804
  class ArrayExpression extends NodeBase {
3679
3805
  constructor() {
3680
3806
  super(...arguments);
@@ -3695,6 +3821,16 @@ class ArrayExpression extends NodeBase {
3695
3821
  hasEffectsOnInteractionAtPath(path, interaction, context) {
3696
3822
  return this.getObjectEntity().hasEffectsOnInteractionAtPath(path, interaction, context);
3697
3823
  }
3824
+ includeNode(context) {
3825
+ this.included = true;
3826
+ if (!this.deoptimized)
3827
+ this.applyDeoptimizations();
3828
+ for (const element of this.elements) {
3829
+ if (element) {
3830
+ element?.includePath(UNKNOWN_PATH, context);
3831
+ }
3832
+ }
3833
+ }
3698
3834
  applyDeoptimizations() {
3699
3835
  this.deoptimized = true;
3700
3836
  let hasSpread = false;
@@ -4762,17 +4898,37 @@ class GlobalVariable extends Variable {
4762
4898
  }
4763
4899
  }
4764
4900
 
4901
+ // To avoid infinite recursions
4902
+ const MAX_PATH_DEPTH = 6;
4903
+ // If a path is longer than MAX_PATH_DEPTH, it is truncated so that it is at
4904
+ // most MAX_PATH_DEPTH long. The last element is always UnknownKey
4905
+ const limitConcatenatedPathDepth = (path1, path2) => {
4906
+ const { length: length1 } = path1;
4907
+ const { length: length2 } = path2;
4908
+ return length1 === 0
4909
+ ? path2
4910
+ : length2 === 0
4911
+ ? path1
4912
+ : length1 + length2 > MAX_PATH_DEPTH
4913
+ ? [...path1, ...path2.slice(0, MAX_PATH_DEPTH - 1 - path1.length), 'UnknownKey']
4914
+ : [...path1, ...path2];
4915
+ };
4916
+
4765
4917
  class LocalVariable extends Variable {
4766
- constructor(name, declarator, init, context, kind) {
4918
+ constructor(name, declarator, init,
4919
+ /** if this is non-empty, the actual init is this path of this.init */
4920
+ initPath, context, kind) {
4767
4921
  super(name);
4768
4922
  this.init = init;
4923
+ this.initPath = initPath;
4924
+ this.kind = kind;
4769
4925
  this.calledFromTryStatement = false;
4770
4926
  this.additionalInitializers = null;
4927
+ this.includedPathTracker = new IncludedPathTracker();
4771
4928
  this.expressionsToBeDeoptimized = [];
4772
4929
  this.declarations = declarator ? [declarator] : [];
4773
4930
  this.deoptimizationTracker = context.deoptimizationTracker;
4774
4931
  this.module = context.module;
4775
- this.kind = kind;
4776
4932
  }
4777
4933
  addDeclaration(identifier, init) {
4778
4934
  this.declarations.push(identifier);
@@ -4783,15 +4939,16 @@ class LocalVariable extends Variable {
4783
4939
  for (const initializer of this.additionalInitializers) {
4784
4940
  initializer.deoptimizePath(UNKNOWN_PATH);
4785
4941
  }
4786
- this.additionalInitializers = null;
4787
4942
  }
4788
4943
  }
4789
4944
  deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
4790
- if (this.isReassigned) {
4945
+ if (this.isReassigned || path.length + this.initPath.length > MAX_PATH_DEPTH) {
4791
4946
  deoptimizeInteraction(interaction);
4792
4947
  return;
4793
4948
  }
4794
- recursionTracker.withTrackedEntityAtPath(path, this.init, () => this.init.deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker), undefined);
4949
+ recursionTracker.withTrackedEntityAtPath(path, this.init, () => {
4950
+ this.init.deoptimizeArgumentsOnInteractionAtPath(interaction, [...this.initPath, ...path], recursionTracker);
4951
+ }, undefined);
4795
4952
  }
4796
4953
  deoptimizePath(path) {
4797
4954
  if (this.isReassigned ||
@@ -4805,37 +4962,40 @@ class LocalVariable extends Variable {
4805
4962
  for (const expression of expressionsToBeDeoptimized) {
4806
4963
  expression.deoptimizeCache();
4807
4964
  }
4808
- this.init.deoptimizePath(UNKNOWN_PATH);
4965
+ this.init.deoptimizePath([...this.initPath, UnknownKey]);
4809
4966
  }
4810
4967
  else {
4811
- this.init.deoptimizePath(path);
4968
+ this.init.deoptimizePath(limitConcatenatedPathDepth(this.initPath, path));
4812
4969
  }
4813
4970
  }
4814
4971
  getLiteralValueAtPath(path, recursionTracker, origin) {
4815
- if (this.isReassigned) {
4972
+ if (this.isReassigned || path.length + this.initPath.length > MAX_PATH_DEPTH) {
4816
4973
  return UnknownValue;
4817
4974
  }
4818
4975
  return recursionTracker.withTrackedEntityAtPath(path, this.init, () => {
4819
4976
  this.expressionsToBeDeoptimized.push(origin);
4820
- return this.init.getLiteralValueAtPath(path, recursionTracker, origin);
4977
+ return this.init.getLiteralValueAtPath([...this.initPath, ...path], recursionTracker, origin);
4821
4978
  }, UnknownValue);
4822
4979
  }
4823
4980
  getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin) {
4824
- if (this.isReassigned) {
4981
+ if (this.isReassigned || path.length + this.initPath.length > MAX_PATH_DEPTH) {
4825
4982
  return UNKNOWN_RETURN_EXPRESSION;
4826
4983
  }
4827
4984
  return recursionTracker.withTrackedEntityAtPath(path, this.init, () => {
4828
4985
  this.expressionsToBeDeoptimized.push(origin);
4829
- return this.init.getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin);
4986
+ return this.init.getReturnExpressionWhenCalledAtPath([...this.initPath, ...path], interaction, recursionTracker, origin);
4830
4987
  }, UNKNOWN_RETURN_EXPRESSION);
4831
4988
  }
4832
4989
  hasEffectsOnInteractionAtPath(path, interaction, context) {
4990
+ if (path.length + this.initPath.length > MAX_PATH_DEPTH) {
4991
+ return true;
4992
+ }
4833
4993
  switch (interaction.type) {
4834
4994
  case INTERACTION_ACCESSED: {
4835
4995
  if (this.isReassigned)
4836
4996
  return true;
4837
4997
  return (!context.accessed.trackEntityAtPathAndGetIfTracked(path, this) &&
4838
- this.init.hasEffectsOnInteractionAtPath(path, interaction, context));
4998
+ this.init.hasEffectsOnInteractionAtPath([...this.initPath, ...path], interaction, context));
4839
4999
  }
4840
5000
  case INTERACTION_ASSIGNED: {
4841
5001
  if (this.included)
@@ -4845,44 +5005,63 @@ class LocalVariable extends Variable {
4845
5005
  if (this.isReassigned)
4846
5006
  return true;
4847
5007
  return (!context.assigned.trackEntityAtPathAndGetIfTracked(path, this) &&
4848
- this.init.hasEffectsOnInteractionAtPath(path, interaction, context));
5008
+ this.init.hasEffectsOnInteractionAtPath([...this.initPath, ...path], interaction, context));
4849
5009
  }
4850
5010
  case INTERACTION_CALLED: {
4851
5011
  if (this.isReassigned)
4852
5012
  return true;
4853
5013
  return (!(interaction.withNew ? context.instantiated : context.called).trackEntityAtPathAndGetIfTracked(path, interaction.args, this) &&
4854
- this.init.hasEffectsOnInteractionAtPath(path, interaction, context));
5014
+ this.init.hasEffectsOnInteractionAtPath([...this.initPath, ...path], interaction, context));
4855
5015
  }
4856
5016
  }
4857
5017
  }
4858
- include() {
4859
- if (!this.included) {
4860
- super.include();
5018
+ includePath(path, context) {
5019
+ if (!this.includedPathTracker.includePathAndGetIfIncluded(path)) {
5020
+ this.module.scope.context.requestTreeshakingPass();
5021
+ if (!this.included) {
5022
+ // This will reduce the number of tree-shaking passes by eagerly
5023
+ // including inits. By pushing this here instead of directly including
5024
+ // we avoid deep call stacks.
5025
+ this.module.scope.context.newlyIncludedVariableInits.add(this.init);
5026
+ }
5027
+ super.includePath(path, context);
4861
5028
  for (const declaration of this.declarations) {
4862
5029
  // If node is a default export, it can save a tree-shaking run to include the full declaration now
4863
5030
  if (!declaration.included)
4864
- declaration.include(createInclusionContext(), false);
5031
+ declaration.include(context, false);
4865
5032
  let node = declaration.parent;
4866
5033
  while (!node.included) {
4867
5034
  // We do not want to properly include parents in case they are part of a dead branch
4868
5035
  // in which case .include() might pull in more dead code
4869
- node.included = true;
5036
+ node.includeNode(context);
4870
5037
  if (node.type === Program$1)
4871
5038
  break;
4872
5039
  node = node.parent;
4873
5040
  }
4874
5041
  }
5042
+ // We need to make sure we include the correct path of the init
5043
+ if (path.length > 0) {
5044
+ this.init.includePath(limitConcatenatedPathDepth(this.initPath, path), context);
5045
+ this.additionalInitializers?.forEach(initializer => initializer.includePath(UNKNOWN_PATH, context));
5046
+ }
4875
5047
  }
4876
5048
  }
4877
- includeCallArguments(context, parameters) {
4878
- if (this.isReassigned || context.includedCallArguments.has(this.init)) {
4879
- for (const argument of parameters) {
4880
- argument.include(context, false);
5049
+ includeCallArguments(context, interaction) {
5050
+ if (this.isReassigned ||
5051
+ context.includedCallArguments.has(this.init) ||
5052
+ // This can be removed again once we can include arguments when called at
5053
+ // a specific path
5054
+ this.initPath.length > 0) {
5055
+ for (const argument of interaction.args) {
5056
+ if (argument) {
5057
+ argument.includePath(UNKNOWN_PATH, context);
5058
+ argument.include(context, false);
5059
+ }
4881
5060
  }
4882
5061
  }
4883
5062
  else {
4884
5063
  context.includedCallArguments.add(this.init);
4885
- this.init.includeCallArguments(context, parameters);
5064
+ this.init.includeCallArguments(context, interaction);
4886
5065
  context.includedCallArguments.delete(this.init);
4887
5066
  }
4888
5067
  }
@@ -4962,18 +5141,31 @@ class IdentifierBase extends NodeBase {
4962
5141
  }
4963
5142
  }
4964
5143
  }
4965
- include() {
5144
+ include(context) {
5145
+ if (!this.included)
5146
+ this.includeNode(context);
5147
+ }
5148
+ includeNode(context) {
5149
+ this.included = true;
4966
5150
  if (!this.deoptimized)
4967
5151
  this.applyDeoptimizations();
5152
+ if (this.variable !== null) {
5153
+ this.scope.context.includeVariableInModule(this.variable, EMPTY_PATH, context);
5154
+ }
5155
+ }
5156
+ includePath(path, context) {
4968
5157
  if (!this.included) {
4969
5158
  this.included = true;
4970
5159
  if (this.variable !== null) {
4971
- this.scope.context.includeVariableInModule(this.variable);
5160
+ this.scope.context.includeVariableInModule(this.variable, path, context);
4972
5161
  }
4973
5162
  }
5163
+ else if (path.length > 0) {
5164
+ this.variable?.includePath(path, context);
5165
+ }
4974
5166
  }
4975
- includeCallArguments(context, parameters) {
4976
- this.variable.includeCallArguments(context, parameters);
5167
+ includeCallArguments(context, interaction) {
5168
+ this.variable.includeCallArguments(context, interaction);
4977
5169
  }
4978
5170
  isPossibleTDZ() {
4979
5171
  // return cached value to avoid issues with the next tree-shaking pass
@@ -5056,11 +5248,40 @@ function closestParentFunctionOrProgram(node) {
5056
5248
  return node;
5057
5249
  }
5058
5250
 
5251
+ class ObjectMember extends ExpressionEntity {
5252
+ constructor(object, path) {
5253
+ super();
5254
+ this.object = object;
5255
+ this.path = path;
5256
+ }
5257
+ deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
5258
+ this.object.deoptimizeArgumentsOnInteractionAtPath(interaction, [...this.path, ...path], recursionTracker);
5259
+ }
5260
+ deoptimizePath(path) {
5261
+ this.object.deoptimizePath([...this.path, ...path]);
5262
+ }
5263
+ getLiteralValueAtPath(path, recursionTracker, origin) {
5264
+ return this.object.getLiteralValueAtPath([...this.path, ...path], recursionTracker, origin);
5265
+ }
5266
+ getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin) {
5267
+ return this.object.getReturnExpressionWhenCalledAtPath([...this.path, ...path], interaction, recursionTracker, origin);
5268
+ }
5269
+ hasEffectsOnInteractionAtPath(path, interaction, context) {
5270
+ return this.object.hasEffectsOnInteractionAtPath([...this.path, ...path], interaction, context);
5271
+ }
5272
+ }
5273
+
5059
5274
  class Identifier extends IdentifierBase {
5060
5275
  constructor() {
5061
5276
  super(...arguments);
5062
5277
  this.variable = null;
5063
5278
  }
5279
+ get isDestructuringDeoptimized() {
5280
+ return isFlagSet(this.flags, 8388608 /* Flag.destructuringDeoptimized */);
5281
+ }
5282
+ set isDestructuringDeoptimized(value) {
5283
+ this.flags = setFlag(this.flags, 8388608 /* Flag.destructuringDeoptimized */, value);
5284
+ }
5064
5285
  addExportedVariables(variables, exportNamesByVariable) {
5065
5286
  if (exportNamesByVariable.has(this.variable)) {
5066
5287
  variables.push(this.variable);
@@ -5073,43 +5294,53 @@ class Identifier extends IdentifierBase {
5073
5294
  this.isVariableReference = true;
5074
5295
  }
5075
5296
  }
5076
- declare(kind, init) {
5297
+ declare(kind, destructuredInitPath, init) {
5077
5298
  let variable;
5078
5299
  const { treeshake } = this.scope.context.options;
5079
- switch (kind) {
5080
- case 'var': {
5081
- variable = this.scope.addDeclaration(this, this.scope.context, init, kind);
5082
- if (treeshake && treeshake.correctVarValueBeforeDeclaration) {
5083
- // Necessary to make sure the init is deoptimized. We cannot call deoptimizePath here.
5084
- variable.markInitializersForDeoptimization();
5085
- }
5086
- break;
5087
- }
5088
- case 'function': {
5089
- // in strict mode, functions are only hoisted within a scope but not across block scopes
5090
- variable = this.scope.addDeclaration(this, this.scope.context, init, kind);
5091
- break;
5092
- }
5093
- case 'let':
5094
- case 'const':
5095
- case 'using':
5096
- case 'await using':
5097
- case 'class': {
5098
- variable = this.scope.addDeclaration(this, this.scope.context, init, kind);
5099
- break;
5100
- }
5101
- case 'parameter': {
5102
- variable = this.scope.addParameterDeclaration(this);
5103
- break;
5104
- }
5105
- /* istanbul ignore next */
5106
- default: {
5107
- /* istanbul ignore next */
5108
- throw new Error(`Internal Error: Unexpected identifier kind ${kind}.`);
5300
+ if (kind === 'parameter') {
5301
+ variable = this.scope.addParameterDeclaration(this, destructuredInitPath);
5302
+ }
5303
+ else {
5304
+ variable = this.scope.addDeclaration(this, this.scope.context, init, destructuredInitPath, kind);
5305
+ if (kind === 'var' && treeshake && treeshake.correctVarValueBeforeDeclaration) {
5306
+ // Necessary to make sure the init is deoptimized. We cannot call deoptimizePath here.
5307
+ variable.markInitializersForDeoptimization();
5109
5308
  }
5110
5309
  }
5111
5310
  return [(this.variable = variable)];
5112
5311
  }
5312
+ deoptimizeAssignment(destructuredInitPath, init) {
5313
+ this.deoptimizePath(EMPTY_PATH);
5314
+ init.deoptimizePath([...destructuredInitPath, UnknownKey]);
5315
+ }
5316
+ hasEffectsWhenDestructuring(context, destructuredInitPath, init) {
5317
+ return (destructuredInitPath.length > 0 &&
5318
+ init.hasEffectsOnInteractionAtPath(destructuredInitPath, NODE_INTERACTION_UNKNOWN_ACCESS, context));
5319
+ }
5320
+ includeDestructuredIfNecessary(context, destructuredInitPath, init) {
5321
+ if (destructuredInitPath.length > 0 && !this.isDestructuringDeoptimized) {
5322
+ this.isDestructuringDeoptimized = true;
5323
+ init.deoptimizeArgumentsOnInteractionAtPath({
5324
+ args: [new ObjectMember(init, destructuredInitPath.slice(0, -1))],
5325
+ type: INTERACTION_ACCESSED
5326
+ }, destructuredInitPath, SHARED_RECURSION_TRACKER);
5327
+ }
5328
+ const { propertyReadSideEffects } = this.scope.context.options
5329
+ .treeshake;
5330
+ if ((this.included ||=
5331
+ destructuredInitPath.length > 0 &&
5332
+ !context.brokenFlow &&
5333
+ propertyReadSideEffects &&
5334
+ (propertyReadSideEffects === 'always' ||
5335
+ init.hasEffectsOnInteractionAtPath(destructuredInitPath, NODE_INTERACTION_UNKNOWN_ACCESS, createHasEffectsContext())))) {
5336
+ if (this.variable && !this.variable.included) {
5337
+ this.scope.context.includeVariableInModule(this.variable, EMPTY_PATH, context);
5338
+ }
5339
+ init.includePath(destructuredInitPath, context);
5340
+ return true;
5341
+ }
5342
+ return false;
5343
+ }
5113
5344
  markDeclarationReached() {
5114
5345
  this.variable.initReached = true;
5115
5346
  }
@@ -5174,18 +5405,17 @@ class Scope {
5174
5405
  - then the variable is still declared in the hoisted outer scope, but the initializer is assigned to the parameter
5175
5406
  - const, let, class, and function except in the cases above cannot redeclare anything
5176
5407
  */
5177
- addDeclaration(identifier, context, init, kind) {
5408
+ addDeclaration(identifier, context, init, destructuredInitPath, kind) {
5178
5409
  const name = identifier.name;
5179
5410
  const existingVariable = this.hoistedVariables?.get(name) || this.variables.get(name);
5180
5411
  if (existingVariable) {
5181
- const existingKind = existingVariable.kind;
5182
- if (kind === 'var' && existingKind === 'var') {
5412
+ if (kind === 'var' && existingVariable.kind === 'var') {
5183
5413
  existingVariable.addDeclaration(identifier, init);
5184
5414
  return existingVariable;
5185
5415
  }
5186
5416
  context.error(logRedeclarationError(name), identifier.start);
5187
5417
  }
5188
- const newVariable = new LocalVariable(identifier.name, identifier, init, context, kind);
5418
+ const newVariable = new LocalVariable(identifier.name, identifier, init, destructuredInitPath, context, kind);
5189
5419
  this.variables.set(name, newVariable);
5190
5420
  return newVariable;
5191
5421
  }
@@ -5361,7 +5591,6 @@ class MethodBase extends NodeBase {
5361
5591
  }
5362
5592
  return this.getAccessedValue()[0].hasEffectsOnInteractionAtPath(path, interaction, context);
5363
5593
  }
5364
- applyDeoptimizations() { }
5365
5594
  getAccessedValue() {
5366
5595
  if (this.accessedValue === null) {
5367
5596
  if (this.kind === 'get') {
@@ -5375,19 +5604,20 @@ class MethodBase extends NodeBase {
5375
5604
  return this.accessedValue;
5376
5605
  }
5377
5606
  }
5607
+ MethodBase.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
5608
+ MethodBase.prototype.applyDeoptimizations = doNotDeoptimize;
5378
5609
 
5379
5610
  class MethodDefinition extends MethodBase {
5380
5611
  hasEffects(context) {
5381
5612
  return super.hasEffects(context) || checkEffectForNodes(this.decorators, context);
5382
5613
  }
5383
- applyDeoptimizations() { }
5384
5614
  }
5385
5615
 
5386
5616
  class BlockScope extends ChildScope {
5387
5617
  constructor(parent) {
5388
5618
  super(parent, parent.context);
5389
5619
  }
5390
- addDeclaration(identifier, context, init, kind) {
5620
+ addDeclaration(identifier, context, init, destructuredInitPath, kind) {
5391
5621
  if (kind === 'var') {
5392
5622
  const name = identifier.name;
5393
5623
  const existingVariable = this.hoistedVariables?.get(name) || this.variables.get(name);
@@ -5399,7 +5629,7 @@ class BlockScope extends ChildScope {
5399
5629
  }
5400
5630
  return context.error(logRedeclarationError(name), identifier.start);
5401
5631
  }
5402
- const declaredVariable = this.parent.addDeclaration(identifier, context, init, kind);
5632
+ const declaredVariable = this.parent.addDeclaration(identifier, context, init, destructuredInitPath, kind);
5403
5633
  // Necessary to make sure the init is deoptimized for conditional declarations.
5404
5634
  // We cannot call deoptimizePath here.
5405
5635
  declaredVariable.markInitializersForDeoptimization();
@@ -5407,7 +5637,7 @@ class BlockScope extends ChildScope {
5407
5637
  this.addHoistedVariable(name, declaredVariable);
5408
5638
  return declaredVariable;
5409
5639
  }
5410
- return super.addDeclaration(identifier, context, init, kind);
5640
+ return super.addDeclaration(identifier, context, init, destructuredInitPath, kind);
5411
5641
  }
5412
5642
  }
5413
5643
 
@@ -5439,33 +5669,12 @@ class StaticBlock extends NodeBase {
5439
5669
  }
5440
5670
  }
5441
5671
  }
5672
+ StaticBlock.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
5673
+ StaticBlock.prototype.applyDeoptimizations = doNotDeoptimize;
5442
5674
  function isStaticBlock(statement) {
5443
5675
  return statement.type === StaticBlock$1;
5444
5676
  }
5445
5677
 
5446
- class ObjectMember extends ExpressionEntity {
5447
- constructor(object, key) {
5448
- super();
5449
- this.object = object;
5450
- this.key = key;
5451
- }
5452
- deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
5453
- this.object.deoptimizeArgumentsOnInteractionAtPath(interaction, [this.key, ...path], recursionTracker);
5454
- }
5455
- deoptimizePath(path) {
5456
- this.object.deoptimizePath([this.key, ...path]);
5457
- }
5458
- getLiteralValueAtPath(path, recursionTracker, origin) {
5459
- return this.object.getLiteralValueAtPath([this.key, ...path], recursionTracker, origin);
5460
- }
5461
- getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin) {
5462
- return this.object.getReturnExpressionWhenCalledAtPath([this.key, ...path], interaction, recursionTracker, origin);
5463
- }
5464
- hasEffectsOnInteractionAtPath(path, interaction, context) {
5465
- return this.object.hasEffectsOnInteractionAtPath([this.key, ...path], interaction, context);
5466
- }
5467
- }
5468
-
5469
5678
  class ClassNode extends NodeBase {
5470
5679
  constructor() {
5471
5680
  super(...arguments);
@@ -5506,21 +5715,20 @@ class ClassNode extends NodeBase {
5506
5715
  : this.getObjectEntity().hasEffectsOnInteractionAtPath(path, interaction, context);
5507
5716
  }
5508
5717
  include(context, includeChildrenRecursively) {
5509
- if (!this.deoptimized)
5510
- this.applyDeoptimizations();
5511
- this.included = true;
5718
+ if (!this.included)
5719
+ this.includeNode(context);
5512
5720
  this.superClass?.include(context, includeChildrenRecursively);
5513
5721
  this.body.include(context, includeChildrenRecursively);
5514
5722
  for (const decorator of this.decorators)
5515
5723
  decorator.include(context, includeChildrenRecursively);
5516
5724
  if (this.id) {
5517
5725
  this.id.markDeclarationReached();
5518
- this.id.include();
5726
+ this.id.include(context);
5519
5727
  }
5520
5728
  }
5521
5729
  initialise() {
5522
5730
  super.initialise();
5523
- this.id?.declare('class', this);
5731
+ this.id?.declare('class', EMPTY_PATH, this);
5524
5732
  for (const method of this.body.body) {
5525
5733
  if (method instanceof MethodDefinition && method.kind === 'constructor') {
5526
5734
  this.classConstructor = method;
@@ -5578,11 +5786,12 @@ class ClassNode extends NodeBase {
5578
5786
  staticProperties.unshift({
5579
5787
  key: 'prototype',
5580
5788
  kind: 'init',
5581
- property: new ObjectEntity(dynamicMethods, this.superClass ? new ObjectMember(this.superClass, 'prototype') : OBJECT_PROTOTYPE)
5789
+ property: new ObjectEntity(dynamicMethods, this.superClass ? new ObjectMember(this.superClass, ['prototype']) : OBJECT_PROTOTYPE)
5582
5790
  });
5583
5791
  return (this.objectEntity = new ObjectEntity(staticProperties, this.superClass || OBJECT_PROTOTYPE));
5584
5792
  }
5585
5793
  }
5794
+ ClassNode.prototype.includeNode = onlyIncludeSelf;
5586
5795
 
5587
5796
  class ClassDeclaration extends ClassNode {
5588
5797
  initialise() {
@@ -5635,7 +5844,7 @@ class ClassDeclaration extends ClassNode {
5635
5844
 
5636
5845
  class ArgumentsVariable extends LocalVariable {
5637
5846
  constructor(context) {
5638
- super('arguments', null, UNKNOWN_EXPRESSION, context, 'other');
5847
+ super('arguments', null, UNKNOWN_EXPRESSION, EMPTY_PATH, context, 'other');
5639
5848
  this.deoptimizedArguments = [];
5640
5849
  }
5641
5850
  addArgumentToBeDeoptimized(argument) {
@@ -5649,8 +5858,8 @@ class ArgumentsVariable extends LocalVariable {
5649
5858
  hasEffectsOnInteractionAtPath(path, { type }) {
5650
5859
  return type !== INTERACTION_ACCESSED || path.length > 1;
5651
5860
  }
5652
- include() {
5653
- super.include();
5861
+ includePath(path, context) {
5862
+ super.includePath(path, context);
5654
5863
  for (const argument of this.deoptimizedArguments) {
5655
5864
  argument.deoptimizePath(UNKNOWN_PATH);
5656
5865
  }
@@ -5661,27 +5870,28 @@ class ArgumentsVariable extends LocalVariable {
5661
5870
  const MAX_TRACKED_INTERACTIONS = 20;
5662
5871
  const NO_INTERACTIONS = EMPTY_ARRAY;
5663
5872
  const UNKNOWN_DEOPTIMIZED_FIELD = new Set([UnknownKey]);
5664
- const EMPTY_PATH_TRACKER = new PathTracker();
5873
+ const EMPTY_PATH_TRACKER = new EntityPathTracker();
5665
5874
  const UNKNOWN_DEOPTIMIZED_ENTITY = new Set([UNKNOWN_EXPRESSION]);
5666
5875
  class ParameterVariable extends LocalVariable {
5667
- constructor(name, declarator, context) {
5668
- super(name, declarator, UNKNOWN_EXPRESSION, context, 'parameter');
5876
+ constructor(name, declarator, argumentPath, context) {
5877
+ super(name, declarator, UNKNOWN_EXPRESSION, argumentPath, context, 'parameter');
5669
5878
  this.deoptimizationInteractions = [];
5670
- this.deoptimizations = new PathTracker();
5879
+ this.deoptimizations = new EntityPathTracker();
5671
5880
  this.deoptimizedFields = new Set();
5672
- this.entitiesToBeDeoptimized = new Set();
5673
- this.expressionsUseTheKnownValue = [];
5881
+ this.argumentsToBeDeoptimized = new Set();
5882
+ this.expressionsDependingOnKnownValue = [];
5674
5883
  this.knownValue = null;
5675
5884
  this.knownValueLiteral = UnknownValue;
5676
5885
  this.frozenValue = null;
5677
5886
  }
5678
- addEntityToBeDeoptimized(entity) {
5887
+ addArgumentValue(entity) {
5888
+ this.updateKnownValue(entity);
5679
5889
  if (entity === UNKNOWN_EXPRESSION) {
5680
5890
  // As unknown expressions fully deoptimize all interactions, we can clear
5681
5891
  // the interaction cache at this point provided we keep this optimization
5682
5892
  // in mind when adding new interactions
5683
- if (!this.entitiesToBeDeoptimized.has(UNKNOWN_EXPRESSION)) {
5684
- this.entitiesToBeDeoptimized.add(UNKNOWN_EXPRESSION);
5893
+ if (!this.argumentsToBeDeoptimized.has(UNKNOWN_EXPRESSION)) {
5894
+ this.argumentsToBeDeoptimized.add(UNKNOWN_EXPRESSION);
5685
5895
  for (const { interaction } of this.deoptimizationInteractions) {
5686
5896
  deoptimizeInteraction(interaction);
5687
5897
  }
@@ -5691,27 +5901,34 @@ class ParameterVariable extends LocalVariable {
5691
5901
  else if (this.deoptimizedFields.has(UnknownKey)) {
5692
5902
  // This means that we already deoptimized all interactions and no longer
5693
5903
  // track them
5694
- entity.deoptimizePath(UNKNOWN_PATH);
5904
+ entity.deoptimizePath([...this.initPath, UnknownKey]);
5695
5905
  }
5696
- else if (!this.entitiesToBeDeoptimized.has(entity)) {
5697
- this.entitiesToBeDeoptimized.add(entity);
5906
+ else if (!this.argumentsToBeDeoptimized.has(entity)) {
5907
+ this.argumentsToBeDeoptimized.add(entity);
5698
5908
  for (const field of this.deoptimizedFields) {
5699
- entity.deoptimizePath([field]);
5909
+ entity.deoptimizePath([...this.initPath, field]);
5700
5910
  }
5701
5911
  for (const { interaction, path } of this.deoptimizationInteractions) {
5702
- entity.deoptimizeArgumentsOnInteractionAtPath(interaction, path, SHARED_RECURSION_TRACKER);
5912
+ if (this.initPath.length + path.length > MAX_PATH_DEPTH) {
5913
+ deoptimizeInteraction(interaction);
5914
+ continue;
5915
+ }
5916
+ entity.deoptimizeArgumentsOnInteractionAtPath(interaction, [...this.initPath, ...path], SHARED_RECURSION_TRACKER);
5703
5917
  }
5704
5918
  }
5705
5919
  }
5920
+ /** This says we should not make assumptions about the value of the parameter.
5921
+ * This is different from deoptimization that will also cause argument values
5922
+ * to be deoptimized. */
5706
5923
  markReassigned() {
5707
5924
  if (this.isReassigned) {
5708
5925
  return;
5709
5926
  }
5710
5927
  super.markReassigned();
5711
- for (const expression of this.expressionsUseTheKnownValue) {
5928
+ for (const expression of this.expressionsDependingOnKnownValue) {
5712
5929
  expression.deoptimizeCache();
5713
5930
  }
5714
- this.expressionsUseTheKnownValue = EMPTY_ARRAY;
5931
+ this.expressionsDependingOnKnownValue = EMPTY_ARRAY;
5715
5932
  }
5716
5933
  deoptimizeCache() {
5717
5934
  this.markReassigned();
@@ -5728,7 +5945,7 @@ class ParameterVariable extends LocalVariable {
5728
5945
  }
5729
5946
  if (this.knownValue === null) {
5730
5947
  this.knownValue = argument;
5731
- this.knownValueLiteral = argument.getLiteralValueAtPath(EMPTY_PATH, SHARED_RECURSION_TRACKER, this);
5948
+ this.knownValueLiteral = argument.getLiteralValueAtPath(this.initPath, SHARED_RECURSION_TRACKER, this);
5732
5949
  return;
5733
5950
  }
5734
5951
  // the same literal or identifier, do nothing
@@ -5744,7 +5961,7 @@ class ParameterVariable extends LocalVariable {
5744
5961
  return;
5745
5962
  }
5746
5963
  // add tracking for the new argument
5747
- const newValue = argument.getLiteralValueAtPath(EMPTY_PATH, SHARED_RECURSION_TRACKER, this);
5964
+ const newValue = argument.getLiteralValueAtPath(this.initPath, SHARED_RECURSION_TRACKER, this);
5748
5965
  if (newValue !== oldValue) {
5749
5966
  this.markReassigned();
5750
5967
  }
@@ -5762,24 +5979,31 @@ class ParameterVariable extends LocalVariable {
5762
5979
  return this.frozenValue;
5763
5980
  }
5764
5981
  getLiteralValueAtPath(path, recursionTracker, origin) {
5765
- if (this.isReassigned) {
5982
+ if (this.isReassigned || path.length + this.initPath.length > MAX_PATH_DEPTH) {
5766
5983
  return UnknownValue;
5767
5984
  }
5768
5985
  const knownValue = this.getKnownValue();
5769
- this.expressionsUseTheKnownValue.push(origin);
5770
- return recursionTracker.withTrackedEntityAtPath(path, knownValue, () => knownValue.getLiteralValueAtPath(path, recursionTracker, origin), UnknownValue);
5986
+ this.expressionsDependingOnKnownValue.push(origin);
5987
+ return recursionTracker.withTrackedEntityAtPath(path, knownValue, () => knownValue.getLiteralValueAtPath([...this.initPath, ...path], recursionTracker, origin), UnknownValue);
5771
5988
  }
5772
5989
  hasEffectsOnInteractionAtPath(path, interaction, context) {
5773
- if (this.isReassigned || interaction.type === INTERACTION_ASSIGNED) {
5990
+ const { type } = interaction;
5991
+ if (this.isReassigned ||
5992
+ type === INTERACTION_ASSIGNED ||
5993
+ path.length + this.initPath.length > MAX_PATH_DEPTH) {
5774
5994
  return super.hasEffectsOnInteractionAtPath(path, interaction, context);
5775
5995
  }
5776
- const knownValue = this.getKnownValue();
5777
- return knownValue.hasEffectsOnInteractionAtPath(path, interaction, context);
5996
+ return (!(type === INTERACTION_CALLED
5997
+ ? (interaction.withNew
5998
+ ? context.instantiated
5999
+ : context.called).trackEntityAtPathAndGetIfTracked(path, interaction.args, this)
6000
+ : context.accessed.trackEntityAtPathAndGetIfTracked(path, this)) &&
6001
+ this.getKnownValue().hasEffectsOnInteractionAtPath([...this.initPath, ...path], interaction, context));
5778
6002
  }
5779
6003
  deoptimizeArgumentsOnInteractionAtPath(interaction, path) {
5780
6004
  // For performance reasons, we fully deoptimize all deeper interactions
5781
6005
  if (path.length >= 2 ||
5782
- this.entitiesToBeDeoptimized.has(UNKNOWN_EXPRESSION) ||
6006
+ this.argumentsToBeDeoptimized.has(UNKNOWN_EXPRESSION) ||
5783
6007
  this.deoptimizationInteractions.length >= MAX_TRACKED_INTERACTIONS ||
5784
6008
  (path.length === 1 &&
5785
6009
  (this.deoptimizedFields.has(UnknownKey) ||
@@ -5788,10 +6012,10 @@ class ParameterVariable extends LocalVariable {
5788
6012
  return;
5789
6013
  }
5790
6014
  if (!this.deoptimizations.trackEntityAtPathAndGetIfTracked(path, interaction.args)) {
5791
- for (const entity of this.entitiesToBeDeoptimized) {
5792
- entity.deoptimizeArgumentsOnInteractionAtPath(interaction, path, SHARED_RECURSION_TRACKER);
6015
+ for (const entity of this.argumentsToBeDeoptimized) {
6016
+ entity.deoptimizeArgumentsOnInteractionAtPath(interaction, [...this.initPath, ...path], SHARED_RECURSION_TRACKER);
5793
6017
  }
5794
- if (!this.entitiesToBeDeoptimized.has(UNKNOWN_EXPRESSION)) {
6018
+ if (!this.argumentsToBeDeoptimized.has(UNKNOWN_EXPRESSION)) {
5795
6019
  this.deoptimizationInteractions.push({
5796
6020
  interaction,
5797
6021
  path
@@ -5812,17 +6036,17 @@ class ParameterVariable extends LocalVariable {
5812
6036
  return;
5813
6037
  }
5814
6038
  this.deoptimizedFields.add(key);
5815
- for (const entity of this.entitiesToBeDeoptimized) {
6039
+ for (const entity of this.argumentsToBeDeoptimized) {
5816
6040
  // We do not need a recursion tracker here as we already track whether
5817
6041
  // this field is deoptimized
5818
- entity.deoptimizePath([key]);
6042
+ entity.deoptimizePath([...this.initPath, key]);
5819
6043
  }
5820
6044
  if (key === UnknownKey) {
5821
6045
  // save some memory
5822
6046
  this.deoptimizationInteractions = NO_INTERACTIONS;
5823
6047
  this.deoptimizations = EMPTY_PATH_TRACKER;
5824
6048
  this.deoptimizedFields = UNKNOWN_DEOPTIMIZED_FIELD;
5825
- this.entitiesToBeDeoptimized = UNKNOWN_DEOPTIMIZED_ENTITY;
6049
+ this.argumentsToBeDeoptimized = UNKNOWN_DEOPTIMIZED_ENTITY;
5826
6050
  }
5827
6051
  }
5828
6052
  getReturnExpressionWhenCalledAtPath(path) {
@@ -5837,11 +6061,14 @@ class ParameterVariable extends LocalVariable {
5837
6061
  }
5838
6062
  return UNKNOWN_RETURN_EXPRESSION;
5839
6063
  }
6064
+ includeArgumentPaths(entity, context) {
6065
+ this.includedPathTracker.includeAllPaths(entity, context, this.initPath);
6066
+ }
5840
6067
  }
5841
6068
 
5842
6069
  class ThisVariable extends ParameterVariable {
5843
6070
  constructor(context) {
5844
- super('this', null, context);
6071
+ super('this', null, EMPTY_PATH, context);
5845
6072
  }
5846
6073
  hasEffectsOnInteractionAtPath(path, interaction, context) {
5847
6074
  return (context.replacedVariableInits.get(this) || UNKNOWN_EXPRESSION).hasEffectsOnInteractionAtPath(path, interaction, context);
@@ -5853,7 +6080,7 @@ class CatchBodyScope extends ChildScope {
5853
6080
  super(parent, parent.context);
5854
6081
  this.parent = parent;
5855
6082
  }
5856
- addDeclaration(identifier, context, init, kind) {
6083
+ addDeclaration(identifier, context, init, destructuredInitPath, kind) {
5857
6084
  if (kind === 'var') {
5858
6085
  const name = identifier.name;
5859
6086
  const existingVariable = this.hoistedVariables?.get(name) || this.variables.get(name);
@@ -5866,7 +6093,7 @@ class CatchBodyScope extends ChildScope {
5866
6093
  // the assignment actually goes to the parameter and the var is
5867
6094
  // hoisted without assignment. Locally, it is shadowed by the
5868
6095
  // parameter
5869
- const declaredVariable = this.parent.parent.addDeclaration(identifier, context, UNDEFINED_EXPRESSION, kind);
6096
+ const declaredVariable = this.parent.parent.addDeclaration(identifier, context, UNDEFINED_EXPRESSION, destructuredInitPath, kind);
5870
6097
  // To avoid the need to rewrite the declaration, we link the variable
5871
6098
  // names. If we ever implement a logic that splits initialization and
5872
6099
  // assignment for hoisted vars, the "renderLikeHoisted" logic can be
@@ -5885,7 +6112,7 @@ class CatchBodyScope extends ChildScope {
5885
6112
  return context.error(logRedeclarationError(name), identifier.start);
5886
6113
  }
5887
6114
  // We only add parameters to parameter scopes
5888
- const declaredVariable = this.parent.parent.addDeclaration(identifier, context, init, kind);
6115
+ const declaredVariable = this.parent.parent.addDeclaration(identifier, context, init, destructuredInitPath, kind);
5889
6116
  // Necessary to make sure the init is deoptimized for conditional declarations.
5890
6117
  // We cannot call deoptimizePath here.
5891
6118
  declaredVariable.markInitializersForDeoptimization();
@@ -5893,7 +6120,7 @@ class CatchBodyScope extends ChildScope {
5893
6120
  this.addHoistedVariable(name, declaredVariable);
5894
6121
  return declaredVariable;
5895
6122
  }
5896
- return super.addDeclaration(identifier, context, init, kind);
6123
+ return super.addDeclaration(identifier, context, init, destructuredInitPath, kind);
5897
6124
  }
5898
6125
  }
5899
6126
 
@@ -5903,7 +6130,7 @@ class FunctionBodyScope extends ChildScope {
5903
6130
  }
5904
6131
  // There is stuff that is only allowed in function scopes, i.e. functions can
5905
6132
  // be redeclared, functions and var can redeclare each other
5906
- addDeclaration(identifier, context, init, kind) {
6133
+ addDeclaration(identifier, context, init, destructuredInitPath, kind) {
5907
6134
  const name = identifier.name;
5908
6135
  const existingVariable = this.hoistedVariables?.get(name) || this.variables.get(name);
5909
6136
  if (existingVariable) {
@@ -5915,7 +6142,7 @@ class FunctionBodyScope extends ChildScope {
5915
6142
  }
5916
6143
  context.error(logRedeclarationError(name), identifier.start);
5917
6144
  }
5918
- const newVariable = new LocalVariable(identifier.name, identifier, init, context, kind);
6145
+ const newVariable = new LocalVariable(identifier.name, identifier, init, destructuredInitPath, context, kind);
5919
6146
  this.variables.set(name, newVariable);
5920
6147
  return newVariable;
5921
6148
  }
@@ -5924,21 +6151,21 @@ class FunctionBodyScope extends ChildScope {
5924
6151
  class ParameterScope extends ChildScope {
5925
6152
  constructor(parent, isCatchScope) {
5926
6153
  super(parent, parent.context);
5927
- this.parameters = [];
5928
6154
  this.hasRest = false;
6155
+ this.parameters = [];
5929
6156
  this.bodyScope = isCatchScope ? new CatchBodyScope(this) : new FunctionBodyScope(this);
5930
6157
  }
5931
6158
  /**
5932
6159
  * Adds a parameter to this scope. Parameters must be added in the correct
5933
6160
  * order, i.e. from left to right.
5934
6161
  */
5935
- addParameterDeclaration(identifier) {
6162
+ addParameterDeclaration(identifier, argumentPath) {
5936
6163
  const { name, start } = identifier;
5937
6164
  const existingParameter = this.variables.get(name);
5938
6165
  if (existingParameter) {
5939
6166
  return this.context.error(logDuplicateArgumentNameError(name), start);
5940
6167
  }
5941
- const variable = new ParameterVariable(name, identifier, this.context);
6168
+ const variable = new ParameterVariable(name, identifier, argumentPath, this.context);
5942
6169
  this.variables.set(name, variable);
5943
6170
  // We also add it to the body scope to detect name conflicts with local
5944
6171
  // variables. We still need the intermediate scope, though, as parameter
@@ -5956,42 +6183,56 @@ class ParameterScope extends ChildScope {
5956
6183
  }
5957
6184
  this.hasRest = hasRest;
5958
6185
  }
5959
- includeCallArguments(context, parameters) {
6186
+ includeCallArguments(context, interaction) {
5960
6187
  let calledFromTryStatement = false;
5961
6188
  let argumentIncluded = false;
5962
6189
  const restParameter = this.hasRest && this.parameters[this.parameters.length - 1];
5963
- for (const checkedArgument of parameters) {
5964
- if (checkedArgument instanceof SpreadElement) {
5965
- for (const argument of parameters) {
5966
- argument.include(context, false);
5967
- }
5968
- break;
6190
+ const { args } = interaction;
6191
+ let lastExplicitlyIncludedIndex = args.length - 1;
6192
+ // If there is a SpreadElement, we need to include all arguments after it
6193
+ // because we no longer know which argument corresponds to which parameter.
6194
+ for (let argumentIndex = 1; argumentIndex < args.length; argumentIndex++) {
6195
+ const argument = args[argumentIndex];
6196
+ if (argument instanceof SpreadElement && !argumentIncluded) {
6197
+ argumentIncluded = true;
6198
+ lastExplicitlyIncludedIndex = argumentIndex - 1;
6199
+ }
6200
+ if (argumentIncluded) {
6201
+ argument.includePath(UNKNOWN_PATH, context);
6202
+ argument.include(context, false);
5969
6203
  }
5970
6204
  }
5971
- for (let index = parameters.length - 1; index >= 0; index--) {
5972
- const parameterVariables = this.parameters[index] || restParameter;
5973
- const argument = parameters[index];
6205
+ // Now we go backwards either starting from the last argument or before the
6206
+ // first SpreadElement to ensure all arguments before are included as needed
6207
+ for (let index = lastExplicitlyIncludedIndex; index >= 1; index--) {
6208
+ const parameterVariables = this.parameters[index - 1] || restParameter;
6209
+ const argument = args[index];
5974
6210
  if (parameterVariables) {
5975
6211
  calledFromTryStatement = false;
5976
6212
  if (parameterVariables.length === 0) {
5977
- // handle empty destructuring
6213
+ // handle empty destructuring to avoid destructuring undefined
5978
6214
  argumentIncluded = true;
5979
6215
  }
5980
6216
  else {
5981
6217
  for (const variable of parameterVariables) {
5982
- if (variable.included) {
5983
- argumentIncluded = true;
5984
- }
5985
6218
  if (variable.calledFromTryStatement) {
5986
6219
  calledFromTryStatement = true;
5987
6220
  }
6221
+ if (variable.included) {
6222
+ argumentIncluded = true;
6223
+ if (calledFromTryStatement) {
6224
+ argument.include(context, true);
6225
+ }
6226
+ else {
6227
+ variable.includeArgumentPaths(argument, context);
6228
+ argument.include(context, false);
6229
+ }
6230
+ }
5988
6231
  }
5989
6232
  }
5990
6233
  }
5991
- if (!argumentIncluded && argument.shouldBeIncluded(context)) {
6234
+ if (!argument.included && (argumentIncluded || argument.shouldBeIncluded(context))) {
5992
6235
  argumentIncluded = true;
5993
- }
5994
- if (argumentIncluded) {
5995
6236
  argument.include(context, calledFromTryStatement);
5996
6237
  }
5997
6238
  }
@@ -6007,11 +6248,62 @@ class ReturnValueScope extends ParameterScope {
6007
6248
  addReturnExpression(expression) {
6008
6249
  this.returnExpressions.push(expression);
6009
6250
  }
6251
+ deoptimizeArgumentsOnCall(interaction) {
6252
+ const { parameters } = this;
6253
+ const { args } = interaction;
6254
+ let position = 0;
6255
+ for (; position < args.length - 1; position++) {
6256
+ // Only the "this" argument arg[0] can be null
6257
+ const argument = args[position + 1];
6258
+ if (argument instanceof SpreadElement) {
6259
+ // This deoptimizes the current and remaining parameters and arguments
6260
+ for (; position < parameters.length; position++) {
6261
+ args[position + 1]?.deoptimizePath(UNKNOWN_PATH);
6262
+ parameters[position].forEach(variable => variable.markReassigned());
6263
+ }
6264
+ break;
6265
+ }
6266
+ if (this.hasRest && position >= parameters.length - 1) {
6267
+ argument.deoptimizePath(UNKNOWN_PATH);
6268
+ }
6269
+ else {
6270
+ const variables = parameters[position];
6271
+ if (variables) {
6272
+ for (const variable of variables) {
6273
+ variable.addArgumentValue(argument);
6274
+ }
6275
+ }
6276
+ this.addArgumentToBeDeoptimized(argument);
6277
+ }
6278
+ }
6279
+ const nonRestParameterLength = this.hasRest ? parameters.length - 1 : parameters.length;
6280
+ for (; position < nonRestParameterLength; position++) {
6281
+ for (const variable of parameters[position]) {
6282
+ variable.addArgumentValue(UNDEFINED_EXPRESSION);
6283
+ }
6284
+ }
6285
+ }
6010
6286
  getReturnExpression() {
6011
6287
  if (this.returnExpression === null)
6012
6288
  this.updateReturnExpression();
6013
6289
  return this.returnExpression;
6014
6290
  }
6291
+ deoptimizeAllParameters() {
6292
+ for (const parameter of this.parameters) {
6293
+ for (const variable of parameter) {
6294
+ variable.deoptimizePath(UNKNOWN_PATH);
6295
+ variable.markReassigned();
6296
+ }
6297
+ }
6298
+ }
6299
+ reassignAllParameters() {
6300
+ for (const parameter of this.parameters) {
6301
+ for (const variable of parameter) {
6302
+ variable.markReassigned();
6303
+ }
6304
+ }
6305
+ }
6306
+ addArgumentToBeDeoptimized(_argument) { }
6015
6307
  updateReturnExpression() {
6016
6308
  if (this.returnExpressions.length === 1) {
6017
6309
  this.returnExpression = this.returnExpressions[0];
@@ -6027,24 +6319,30 @@ class ReturnValueScope extends ParameterScope {
6027
6319
 
6028
6320
  class FunctionScope extends ReturnValueScope {
6029
6321
  constructor(parent) {
6030
- const { context } = parent;
6031
6322
  super(parent, false);
6323
+ const { context } = parent;
6032
6324
  this.variables.set('arguments', (this.argumentsVariable = new ArgumentsVariable(context)));
6033
6325
  this.variables.set('this', (this.thisVariable = new ThisVariable(context)));
6034
6326
  }
6035
6327
  findLexicalBoundary() {
6036
6328
  return this;
6037
6329
  }
6038
- includeCallArguments(context, parameters) {
6039
- super.includeCallArguments(context, parameters);
6330
+ includeCallArguments(context, interaction) {
6331
+ super.includeCallArguments(context, interaction);
6040
6332
  if (this.argumentsVariable.included) {
6041
- for (const argument of parameters) {
6042
- if (!argument.included) {
6333
+ const { args } = interaction;
6334
+ for (let argumentIndex = 1; argumentIndex < args.length; argumentIndex++) {
6335
+ const argument = args[argumentIndex];
6336
+ if (argument) {
6337
+ argument.includePath(UNKNOWN_PATH, context);
6043
6338
  argument.include(context, false);
6044
6339
  }
6045
6340
  }
6046
6341
  }
6047
6342
  }
6343
+ addArgumentToBeDeoptimized(argument) {
6344
+ this.argumentsVariable.addArgumentToBeDeoptimized(argument);
6345
+ }
6048
6346
  }
6049
6347
 
6050
6348
  class ExpressionStatement extends NodeBase {
@@ -6072,8 +6370,9 @@ class ExpressionStatement extends NodeBase {
6072
6370
  return this.parent.type !== Program$1;
6073
6371
  return super.shouldBeIncluded(context);
6074
6372
  }
6075
- applyDeoptimizations() { }
6076
6373
  }
6374
+ ExpressionStatement.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
6375
+ ExpressionStatement.prototype.applyDeoptimizations = doNotDeoptimize;
6077
6376
 
6078
6377
  class BlockStatement extends NodeBase {
6079
6378
  get deoptimizeBody() {
@@ -6138,6 +6437,8 @@ class BlockStatement extends NodeBase {
6138
6437
  }
6139
6438
  }
6140
6439
  }
6440
+ BlockStatement.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
6441
+ BlockStatement.prototype.applyDeoptimizations = doNotDeoptimize;
6141
6442
 
6142
6443
  class RestElement extends NodeBase {
6143
6444
  constructor() {
@@ -6147,9 +6448,12 @@ class RestElement extends NodeBase {
6147
6448
  addExportedVariables(variables, exportNamesByVariable) {
6148
6449
  this.argument.addExportedVariables(variables, exportNamesByVariable);
6149
6450
  }
6150
- declare(kind, init) {
6451
+ declare(kind, destructuredInitPath, init) {
6151
6452
  this.declarationInit = init;
6152
- return this.argument.declare(kind, UNKNOWN_EXPRESSION);
6453
+ return this.argument.declare(kind, getIncludedPatternPath$1(destructuredInitPath), init);
6454
+ }
6455
+ deoptimizeAssignment(destructuredInitPath, init) {
6456
+ this.argument.deoptimizeAssignment(getIncludedPatternPath$1(destructuredInitPath), init);
6153
6457
  }
6154
6458
  deoptimizePath(path) {
6155
6459
  if (path.length === 0) {
@@ -6160,6 +6464,20 @@ class RestElement extends NodeBase {
6160
6464
  return (path.length > 0 ||
6161
6465
  this.argument.hasEffectsOnInteractionAtPath(EMPTY_PATH, interaction, context));
6162
6466
  }
6467
+ hasEffectsWhenDestructuring(context, destructuredInitPath, init) {
6468
+ return this.argument.hasEffectsWhenDestructuring(context, getIncludedPatternPath$1(destructuredInitPath), init);
6469
+ }
6470
+ includeDestructuredIfNecessary(context, destructuredInitPath, init) {
6471
+ return (this.included =
6472
+ this.argument.includeDestructuredIfNecessary(context, getIncludedPatternPath$1(destructuredInitPath), init) || this.included);
6473
+ }
6474
+ include(context, includeChildrenRecursively) {
6475
+ if (!this.included)
6476
+ this.includeNode(context);
6477
+ // This should just include the identifier, its properties should be
6478
+ // included where the variable is used.
6479
+ this.argument.include(context, includeChildrenRecursively);
6480
+ }
6163
6481
  markDeclarationReached() {
6164
6482
  this.argument.markDeclarationReached();
6165
6483
  }
@@ -6171,12 +6489,16 @@ class RestElement extends NodeBase {
6171
6489
  }
6172
6490
  }
6173
6491
  }
6492
+ RestElement.prototype.includeNode = onlyIncludeSelf;
6493
+ const getIncludedPatternPath$1 = (destructuredInitPath) => destructuredInitPath.at(-1) === UnknownKey
6494
+ ? destructuredInitPath
6495
+ : [...destructuredInitPath, UnknownKey];
6174
6496
 
6175
6497
  class FunctionBase extends NodeBase {
6176
6498
  constructor() {
6177
6499
  super(...arguments);
6178
- this.objectEntity = null;
6179
6500
  this.parameterVariableValuesDeoptimized = false;
6501
+ this.includeCallArguments = this.scope.includeCallArguments.bind(this.scope);
6180
6502
  }
6181
6503
  get async() {
6182
6504
  return isFlagSet(this.flags, 256 /* Flag.async */);
@@ -6196,53 +6518,9 @@ class FunctionBase extends NodeBase {
6196
6518
  set generator(value) {
6197
6519
  this.flags = setFlag(this.flags, 4194304 /* Flag.generator */, value);
6198
6520
  }
6199
- updateParameterVariableValues(_arguments) {
6200
- for (let position = 0; position < this.params.length; position++) {
6201
- const parameter = this.params[position];
6202
- if (!(parameter instanceof Identifier)) {
6203
- continue;
6204
- }
6205
- const parameterVariable = parameter.variable;
6206
- const argument = _arguments[position + 1] ?? UNDEFINED_EXPRESSION;
6207
- parameterVariable.updateKnownValue(argument);
6208
- }
6209
- }
6210
- deoptimizeParameterVariableValues() {
6211
- for (const parameter of this.params) {
6212
- if (parameter instanceof Identifier) {
6213
- const parameterVariable = parameter.variable;
6214
- parameterVariable.markReassigned();
6215
- }
6216
- }
6217
- }
6218
6521
  deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
6219
- if (interaction.type === INTERACTION_CALLED) {
6220
- const { parameters } = this.scope;
6221
- const { args } = interaction;
6222
- let hasRest = false;
6223
- for (let position = 0; position < args.length - 1; position++) {
6224
- const parameter = this.params[position];
6225
- // Only the "this" argument arg[0] can be null
6226
- const argument = args[position + 1];
6227
- if (argument instanceof SpreadElement) {
6228
- this.deoptimizeParameterVariableValues();
6229
- }
6230
- if (hasRest || parameter instanceof RestElement) {
6231
- hasRest = true;
6232
- argument.deoptimizePath(UNKNOWN_PATH);
6233
- }
6234
- else if (parameter instanceof Identifier) {
6235
- parameters[position][0].addEntityToBeDeoptimized(argument);
6236
- this.addArgumentToBeDeoptimized(argument);
6237
- }
6238
- else if (parameter) {
6239
- argument.deoptimizePath(UNKNOWN_PATH);
6240
- }
6241
- else {
6242
- this.addArgumentToBeDeoptimized(argument);
6243
- }
6244
- }
6245
- this.updateParameterVariableValues(args);
6522
+ if (interaction.type === INTERACTION_CALLED && path.length === 0) {
6523
+ this.scope.deoptimizeArgumentsOnCall(interaction);
6246
6524
  }
6247
6525
  else {
6248
6526
  this.getObjectEntity().deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker);
@@ -6254,12 +6532,7 @@ class FunctionBase extends NodeBase {
6254
6532
  // A reassignment of UNKNOWN_PATH is considered equivalent to having lost track
6255
6533
  // which means the return expression and parameters need to be reassigned
6256
6534
  this.scope.getReturnExpression().deoptimizePath(UNKNOWN_PATH);
6257
- for (const parameterList of this.scope.parameters) {
6258
- for (const parameter of parameterList) {
6259
- parameter.deoptimizePath(UNKNOWN_PATH);
6260
- parameter.markReassigned();
6261
- }
6262
- }
6535
+ this.scope.deoptimizeAllParameters();
6263
6536
  }
6264
6537
  }
6265
6538
  getLiteralValueAtPath(path, recursionTracker, origin) {
@@ -6297,8 +6570,13 @@ class FunctionBase extends NodeBase {
6297
6570
  return true;
6298
6571
  }
6299
6572
  }
6300
- for (const parameter of this.params) {
6301
- if (parameter.hasEffects(context))
6573
+ const { propertyReadSideEffects } = this.scope.context.options
6574
+ .treeshake;
6575
+ for (let index = 0; index < this.params.length; index++) {
6576
+ const parameter = this.params[index];
6577
+ if (parameter.hasEffects(context) ||
6578
+ (propertyReadSideEffects &&
6579
+ parameter.hasEffectsWhenDestructuring(context, EMPTY_PATH, interaction.args[index + 1] || UNDEFINED_EXPRESSION)))
6302
6580
  return true;
6303
6581
  }
6304
6582
  return false;
@@ -6317,21 +6595,17 @@ class FunctionBase extends NodeBase {
6317
6595
  return variable?.getOnlyFunctionCallUsed() ?? false;
6318
6596
  }
6319
6597
  include(context, includeChildrenRecursively) {
6320
- if (!this.parameterVariableValuesDeoptimized && !this.onlyFunctionCallUsed()) {
6598
+ if (!this.included)
6599
+ this.includeNode(context);
6600
+ if (!(this.parameterVariableValuesDeoptimized || this.onlyFunctionCallUsed())) {
6321
6601
  this.parameterVariableValuesDeoptimized = true;
6322
- this.deoptimizeParameterVariableValues();
6602
+ this.scope.reassignAllParameters();
6323
6603
  }
6324
- if (!this.deoptimized)
6325
- this.applyDeoptimizations();
6326
- this.included = true;
6327
6604
  const { brokenFlow } = context;
6328
6605
  context.brokenFlow = false;
6329
6606
  this.body.include(context, includeChildrenRecursively);
6330
6607
  context.brokenFlow = brokenFlow;
6331
6608
  }
6332
- includeCallArguments(context, parameters) {
6333
- this.scope.includeCallArguments(context, parameters);
6334
- }
6335
6609
  initialise() {
6336
6610
  super.initialise();
6337
6611
  if (this.body instanceof BlockStatement) {
@@ -6353,14 +6627,14 @@ class FunctionBase extends NodeBase {
6353
6627
  // so that the scope already knows all parameters and can detect conflicts
6354
6628
  // when parsing the body.
6355
6629
  const parameters = (this.params = params.map((parameter) => new (context.getNodeConstructor(parameter.type))(this, scope).parseNode(parameter)));
6356
- scope.addParameterVariables(parameters.map(parameter => parameter.declare('parameter', UNKNOWN_EXPRESSION)), parameters[parameters.length - 1] instanceof RestElement);
6630
+ scope.addParameterVariables(parameters.map(parameter => parameter.declare('parameter', EMPTY_PATH, UNKNOWN_EXPRESSION)), parameters[parameters.length - 1] instanceof RestElement);
6357
6631
  this.body = new (context.getNodeConstructor(body.type))(this, bodyScope).parseNode(body);
6358
6632
  return super.parseNode(esTreeNode);
6359
6633
  }
6360
- addArgumentToBeDeoptimized(_argument) { }
6361
- applyDeoptimizations() { }
6362
6634
  }
6363
6635
  FunctionBase.prototype.preventChildBlockScope = true;
6636
+ FunctionBase.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
6637
+ FunctionBase.prototype.applyDeoptimizations = doNotDeoptimize;
6364
6638
 
6365
6639
  class FunctionNode extends FunctionBase {
6366
6640
  constructor() {
@@ -6372,18 +6646,16 @@ class FunctionNode extends FunctionBase {
6372
6646
  this.constructedEntity = new ObjectEntity(Object.create(null), OBJECT_PROTOTYPE);
6373
6647
  // This makes sure that all deoptimizations of "this" are applied to the
6374
6648
  // constructed entity.
6375
- this.scope.thisVariable.addEntityToBeDeoptimized(this.constructedEntity);
6649
+ this.scope.thisVariable.addArgumentValue(this.constructedEntity);
6376
6650
  }
6377
6651
  deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
6378
6652
  super.deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker);
6379
6653
  if (interaction.type === INTERACTION_CALLED && path.length === 0 && interaction.args[0]) {
6380
6654
  // args[0] is the "this" argument
6381
- this.scope.thisVariable.addEntityToBeDeoptimized(interaction.args[0]);
6655
+ this.scope.thisVariable.addArgumentValue(interaction.args[0]);
6382
6656
  }
6383
6657
  }
6384
6658
  hasEffects(context) {
6385
- if (!this.deoptimized)
6386
- this.applyDeoptimizations();
6387
6659
  if (this.annotationNoSideEffects) {
6388
6660
  return false;
6389
6661
  }
@@ -6421,7 +6693,7 @@ class FunctionNode extends FunctionBase {
6421
6693
  }
6422
6694
  include(context, includeChildrenRecursively) {
6423
6695
  super.include(context, includeChildrenRecursively);
6424
- this.id?.include();
6696
+ this.id?.include(context);
6425
6697
  const hasArguments = this.scope.argumentsVariable.included;
6426
6698
  for (const parameter of this.params) {
6427
6699
  if (!(parameter instanceof Identifier) || hasArguments) {
@@ -6429,12 +6701,18 @@ class FunctionNode extends FunctionBase {
6429
6701
  }
6430
6702
  }
6431
6703
  }
6704
+ includeNode(context) {
6705
+ this.included = true;
6706
+ const hasArguments = this.scope.argumentsVariable.included;
6707
+ for (const parameter of this.params) {
6708
+ if (!(parameter instanceof Identifier) || hasArguments) {
6709
+ parameter.includePath(UNKNOWN_PATH, context);
6710
+ }
6711
+ }
6712
+ }
6432
6713
  initialise() {
6433
6714
  super.initialise();
6434
- this.id?.declare('function', this);
6435
- }
6436
- addArgumentToBeDeoptimized(argument) {
6437
- this.scope.argumentsVariable.addArgumentToBeDeoptimized(argument);
6715
+ this.id?.declare('function', EMPTY_PATH, this);
6438
6716
  }
6439
6717
  getObjectEntity() {
6440
6718
  if (this.objectEntity !== null) {
@@ -6484,11 +6762,16 @@ function getFunctionIdInsertPosition(code, start) {
6484
6762
  }
6485
6763
  class ExportDefaultDeclaration extends NodeBase {
6486
6764
  include(context, includeChildrenRecursively) {
6487
- super.include(context, includeChildrenRecursively);
6765
+ this.included = true;
6766
+ this.declaration.include(context, includeChildrenRecursively);
6488
6767
  if (includeChildrenRecursively) {
6489
- this.scope.context.includeVariableInModule(this.variable);
6768
+ this.scope.context.includeVariableInModule(this.variable, UNKNOWN_PATH, context);
6490
6769
  }
6491
6770
  }
6771
+ includePath(path, context) {
6772
+ this.included = true;
6773
+ this.declaration.includePath(path, context);
6774
+ }
6492
6775
  initialise() {
6493
6776
  super.initialise();
6494
6777
  const declaration = this.declaration;
@@ -6533,7 +6816,6 @@ class ExportDefaultDeclaration extends NodeBase {
6533
6816
  }
6534
6817
  this.declaration.render(code, options);
6535
6818
  }
6536
- applyDeoptimizations() { }
6537
6819
  renderNamedDeclaration(code, declarationStart, idInsertPosition, options) {
6538
6820
  const { exportNamesByVariable, format, snippets: { getPropertyAccess } } = options;
6539
6821
  const name = this.variable.getName(getPropertyAccess);
@@ -6564,6 +6846,8 @@ class ExportDefaultDeclaration extends NodeBase {
6564
6846
  }
6565
6847
  }
6566
6848
  ExportDefaultDeclaration.prototype.needsBoundaries = true;
6849
+ ExportDefaultDeclaration.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
6850
+ ExportDefaultDeclaration.prototype.applyDeoptimizations = doNotDeoptimize;
6567
6851
 
6568
6852
  const needsEscapeRegEx = /[\n\r'\\\u2028\u2029]/;
6569
6853
  const quoteNewlineRegEx = /([\n\r'\u2028\u2029])/g;
@@ -6833,6 +7117,7 @@ class Literal extends NodeBase {
6833
7117
  }
6834
7118
  }
6835
7119
  }
7120
+ Literal.prototype.includeNode = onlyIncludeSelf;
6836
7121
 
6837
7122
  function getChainElementLiteralValueAtPath(element, object, path, recursionTracker, origin) {
6838
7123
  if ('getLiteralValueAtPathAsChainElement' in object) {
@@ -6848,8 +7133,6 @@ function getChainElementLiteralValueAtPath(element, object, path, recursionTrack
6848
7133
  return element.getLiteralValueAtPath(path, recursionTracker, origin);
6849
7134
  }
6850
7135
 
6851
- // To avoid infinite recursions
6852
- const MAX_PATH_DEPTH = 7;
6853
7136
  function getResolvablePropertyKey(memberExpression) {
6854
7137
  return memberExpression.computed
6855
7138
  ? getResolvableComputedPropertyKey(memberExpression.property)
@@ -6948,18 +7231,25 @@ class MemberExpression extends NodeBase {
6948
7231
  }
6949
7232
  else if (!this.isUndefined) {
6950
7233
  if (path.length < MAX_PATH_DEPTH) {
6951
- this.object.deoptimizeArgumentsOnInteractionAtPath(interaction, [this.getPropertyKey(), ...path], recursionTracker);
7234
+ this.object.deoptimizeArgumentsOnInteractionAtPath(interaction, this.propertyKey === UnknownKey ? UNKNOWN_PATH : [this.propertyKey, ...path], recursionTracker);
6952
7235
  }
6953
7236
  else {
6954
7237
  deoptimizeInteraction(interaction);
6955
7238
  }
6956
7239
  }
6957
7240
  }
7241
+ deoptimizeAssignment(destructuredInitPath, init) {
7242
+ this.deoptimizePath(EMPTY_PATH);
7243
+ init.deoptimizePath([...destructuredInitPath, UnknownKey]);
7244
+ }
6958
7245
  deoptimizeCache() {
6959
7246
  const { expressionsToBeDeoptimized, object } = this;
6960
7247
  this.expressionsToBeDeoptimized = EMPTY_ARRAY;
6961
- this.propertyKey = UnknownKey;
7248
+ this.dynamicPropertyKey = this.propertyKey;
6962
7249
  object.deoptimizePath(UNKNOWN_PATH);
7250
+ if (this.included) {
7251
+ object.includePath(UNKNOWN_PATH, createInclusionContext());
7252
+ }
6963
7253
  for (const expression of expressionsToBeDeoptimized) {
6964
7254
  expression.deoptimizeCache();
6965
7255
  }
@@ -6970,11 +7260,13 @@ class MemberExpression extends NodeBase {
6970
7260
  if (this.variable) {
6971
7261
  this.variable.deoptimizePath(path);
6972
7262
  }
6973
- else if (!this.isUndefined && path.length < MAX_PATH_DEPTH) {
6974
- const propertyKey = this.getPropertyKey();
7263
+ else if (!this.isUndefined) {
7264
+ const { propertyKey } = this;
6975
7265
  this.object.deoptimizePath([
6976
7266
  propertyKey === UnknownKey ? UnknownNonAccessorKey : propertyKey,
6977
- ...path
7267
+ ...(path.length < MAX_PATH_DEPTH
7268
+ ? path
7269
+ : [...path.slice(0, MAX_PATH_DEPTH), UnknownKey])
6978
7270
  ]);
6979
7271
  }
6980
7272
  }
@@ -6985,9 +7277,10 @@ class MemberExpression extends NodeBase {
6985
7277
  if (this.isUndefined) {
6986
7278
  return undefined;
6987
7279
  }
6988
- if (this.propertyKey !== UnknownKey && path.length < MAX_PATH_DEPTH) {
7280
+ const propertyKey = this.getDynamicPropertyKey();
7281
+ if (propertyKey !== UnknownKey && path.length < MAX_PATH_DEPTH) {
6989
7282
  this.expressionsToBeDeoptimized.push(origin);
6990
- return this.object.getLiteralValueAtPath([this.getPropertyKey(), ...path], recursionTracker, origin);
7283
+ return this.object.getLiteralValueAtPath([propertyKey, ...path], recursionTracker, origin);
6991
7284
  }
6992
7285
  return UnknownValue;
6993
7286
  }
@@ -7007,9 +7300,10 @@ class MemberExpression extends NodeBase {
7007
7300
  if (this.isUndefined) {
7008
7301
  return [UNDEFINED_EXPRESSION, false];
7009
7302
  }
7010
- if (this.propertyKey !== UnknownKey && path.length < MAX_PATH_DEPTH) {
7303
+ const propertyKey = this.getDynamicPropertyKey();
7304
+ if (propertyKey !== UnknownKey && path.length < MAX_PATH_DEPTH) {
7011
7305
  this.expressionsToBeDeoptimized.push(origin);
7012
- return this.object.getReturnExpressionWhenCalledAtPath([this.getPropertyKey(), ...path], interaction, recursionTracker, origin);
7306
+ return this.object.getReturnExpressionWhenCalledAtPath([propertyKey, ...path], interaction, recursionTracker, origin);
7013
7307
  }
7014
7308
  return UNKNOWN_RETURN_EXPRESSION;
7015
7309
  }
@@ -7055,14 +7349,45 @@ class MemberExpression extends NodeBase {
7055
7349
  return true;
7056
7350
  }
7057
7351
  if (path.length < MAX_PATH_DEPTH) {
7058
- return this.object.hasEffectsOnInteractionAtPath([this.getPropertyKey(), ...path], interaction, context);
7352
+ return this.object.hasEffectsOnInteractionAtPath([this.getDynamicPropertyKey(), ...path], interaction, context);
7059
7353
  }
7060
7354
  return true;
7061
7355
  }
7356
+ hasEffectsWhenDestructuring(context, destructuredInitPath, init) {
7357
+ return (destructuredInitPath.length > 0 &&
7358
+ init.hasEffectsOnInteractionAtPath(destructuredInitPath, NODE_INTERACTION_UNKNOWN_ACCESS, context));
7359
+ }
7062
7360
  include(context, includeChildrenRecursively) {
7361
+ if (!this.included)
7362
+ this.includeNode(context);
7363
+ this.object.include(context, includeChildrenRecursively);
7364
+ this.property.include(context, includeChildrenRecursively);
7365
+ }
7366
+ includeNode(context) {
7367
+ this.included = true;
7063
7368
  if (!this.deoptimized)
7064
7369
  this.applyDeoptimizations();
7065
- this.includeProperties(context, includeChildrenRecursively);
7370
+ if (this.variable) {
7371
+ this.scope.context.includeVariableInModule(this.variable, EMPTY_PATH, context);
7372
+ }
7373
+ else if (!this.isUndefined) {
7374
+ this.object.includePath([this.propertyKey], context);
7375
+ }
7376
+ }
7377
+ includePath(path, context) {
7378
+ if (!this.included)
7379
+ this.includeNode(context);
7380
+ if (this.variable) {
7381
+ this.variable?.includePath(path, context);
7382
+ }
7383
+ else if (!this.isUndefined) {
7384
+ this.object.includePath([
7385
+ this.propertyKey,
7386
+ ...(path.length < MAX_PATH_DEPTH
7387
+ ? path
7388
+ : [...path.slice(0, MAX_PATH_DEPTH), UnknownKey])
7389
+ ], context);
7390
+ }
7066
7391
  }
7067
7392
  includeAsAssignmentTarget(context, includeChildrenRecursively, deoptimizeAccess) {
7068
7393
  if (!this.assignmentDeoptimized)
@@ -7071,20 +7396,34 @@ class MemberExpression extends NodeBase {
7071
7396
  this.include(context, includeChildrenRecursively);
7072
7397
  }
7073
7398
  else {
7074
- this.includeProperties(context, includeChildrenRecursively);
7399
+ if (!this.included)
7400
+ this.includeNode(context);
7401
+ this.object.include(context, includeChildrenRecursively);
7402
+ this.property.include(context, includeChildrenRecursively);
7075
7403
  }
7076
7404
  }
7077
- includeCallArguments(context, parameters) {
7405
+ includeCallArguments(context, interaction) {
7078
7406
  if (this.variable) {
7079
- this.variable.includeCallArguments(context, parameters);
7407
+ this.variable.includeCallArguments(context, interaction);
7080
7408
  }
7081
7409
  else {
7082
- super.includeCallArguments(context, parameters);
7410
+ super.includeCallArguments(context, interaction);
7411
+ }
7412
+ }
7413
+ includeDestructuredIfNecessary(context, destructuredInitPath, init) {
7414
+ if ((this.included ||=
7415
+ destructuredInitPath.length > 0 &&
7416
+ !context.brokenFlow &&
7417
+ init.hasEffectsOnInteractionAtPath(destructuredInitPath, NODE_INTERACTION_UNKNOWN_ACCESS, createHasEffectsContext()))) {
7418
+ init.include(context, false);
7419
+ return true;
7083
7420
  }
7421
+ return false;
7084
7422
  }
7085
7423
  initialise() {
7086
7424
  super.initialise();
7087
- this.propertyKey = getResolvablePropertyKey(this);
7425
+ this.dynamicPropertyKey = getResolvablePropertyKey(this);
7426
+ this.propertyKey = this.dynamicPropertyKey === null ? UnknownKey : this.dynamicPropertyKey;
7088
7427
  this.accessInteraction = { args: [this.object], type: INTERACTION_ACCESSED };
7089
7428
  }
7090
7429
  render(code, options, { renderedParentType, isCalleeOfRenderedParent, renderedSurroundingElement } = BLANK) {
@@ -7121,8 +7460,7 @@ class MemberExpression extends NodeBase {
7121
7460
  this.bound &&
7122
7461
  propertyReadSideEffects &&
7123
7462
  !(this.variable || this.isUndefined)) {
7124
- const propertyKey = this.getPropertyKey();
7125
- this.object.deoptimizeArgumentsOnInteractionAtPath(this.accessInteraction, [propertyKey], SHARED_RECURSION_TRACKER);
7463
+ this.object.deoptimizeArgumentsOnInteractionAtPath(this.accessInteraction, [this.propertyKey], SHARED_RECURSION_TRACKER);
7126
7464
  this.scope.context.requestTreeshakingPass();
7127
7465
  }
7128
7466
  if (this.variable) {
@@ -7139,7 +7477,7 @@ class MemberExpression extends NodeBase {
7139
7477
  this.bound &&
7140
7478
  propertyReadSideEffects &&
7141
7479
  !(this.variable || this.isUndefined)) {
7142
- this.object.deoptimizeArgumentsOnInteractionAtPath(this.assignmentInteraction, [this.getPropertyKey()], SHARED_RECURSION_TRACKER);
7480
+ this.object.deoptimizeArgumentsOnInteractionAtPath(this.assignmentInteraction, [this.propertyKey], SHARED_RECURSION_TRACKER);
7143
7481
  this.scope.context.requestTreeshakingPass();
7144
7482
  }
7145
7483
  }
@@ -7148,24 +7486,24 @@ class MemberExpression extends NodeBase {
7148
7486
  const variable = this.scope.findVariable(this.object.name);
7149
7487
  if (variable.isNamespace) {
7150
7488
  if (this.variable) {
7151
- this.scope.context.includeVariableInModule(this.variable);
7489
+ this.scope.context.includeVariableInModule(this.variable, UNKNOWN_PATH, createInclusionContext());
7152
7490
  }
7153
7491
  this.scope.context.log(LOGLEVEL_WARN, logIllegalImportReassignment(this.object.name, this.scope.context.module.id), this.start);
7154
7492
  }
7155
7493
  }
7156
7494
  }
7157
- getPropertyKey() {
7158
- if (this.propertyKey === null) {
7159
- this.propertyKey = UnknownKey;
7495
+ getDynamicPropertyKey() {
7496
+ if (this.dynamicPropertyKey === null) {
7497
+ this.dynamicPropertyKey = UnknownKey;
7160
7498
  const value = this.property.getLiteralValueAtPath(EMPTY_PATH, SHARED_RECURSION_TRACKER, this);
7161
- return (this.propertyKey =
7499
+ return (this.dynamicPropertyKey =
7162
7500
  value === SymbolToStringTag
7163
7501
  ? value
7164
7502
  : typeof value === 'symbol'
7165
7503
  ? UnknownKey
7166
7504
  : String(value));
7167
7505
  }
7168
- return this.propertyKey;
7506
+ return this.dynamicPropertyKey;
7169
7507
  }
7170
7508
  hasAccessEffect(context) {
7171
7509
  const { propertyReadSideEffects } = this.scope.context.options
@@ -7173,17 +7511,7 @@ class MemberExpression extends NodeBase {
7173
7511
  return (!(this.variable || this.isUndefined) &&
7174
7512
  propertyReadSideEffects &&
7175
7513
  (propertyReadSideEffects === 'always' ||
7176
- this.object.hasEffectsOnInteractionAtPath([this.getPropertyKey()], this.accessInteraction, context)));
7177
- }
7178
- includeProperties(context, includeChildrenRecursively) {
7179
- if (!this.included) {
7180
- this.included = true;
7181
- if (this.variable) {
7182
- this.scope.context.includeVariableInModule(this.variable);
7183
- }
7184
- }
7185
- this.object.include(context, includeChildrenRecursively);
7186
- this.property.include(context, includeChildrenRecursively);
7514
+ this.object.hasEffectsOnInteractionAtPath([this.getDynamicPropertyKey()], this.accessInteraction, context)));
7187
7515
  }
7188
7516
  }
7189
7517
  function resolveNamespaceVariables(baseVariable, path, astContext) {
@@ -7227,18 +7555,20 @@ class MetaProperty extends NodeBase {
7227
7555
  return path.length > 1 || type !== INTERACTION_ACCESSED;
7228
7556
  }
7229
7557
  include() {
7230
- if (!this.included) {
7231
- this.included = true;
7232
- if (this.meta.name === IMPORT) {
7233
- this.scope.context.addImportMeta(this);
7234
- const parent = this.parent;
7235
- const metaProperty = (this.metaProperty =
7236
- parent instanceof MemberExpression && typeof parent.propertyKey === 'string'
7237
- ? parent.propertyKey
7238
- : null);
7239
- if (metaProperty?.startsWith(FILE_PREFIX)) {
7240
- this.referenceId = metaProperty.slice(FILE_PREFIX.length);
7241
- }
7558
+ if (!this.included)
7559
+ this.includeNode();
7560
+ }
7561
+ includeNode() {
7562
+ this.included = true;
7563
+ if (this.meta.name === IMPORT) {
7564
+ this.scope.context.addImportMeta(this);
7565
+ const parent = this.parent;
7566
+ const metaProperty = (this.metaProperty =
7567
+ parent instanceof MemberExpression && typeof parent.propertyKey === 'string'
7568
+ ? parent.propertyKey
7569
+ : null);
7570
+ if (metaProperty?.startsWith(FILE_PREFIX)) {
7571
+ this.referenceId = metaProperty.slice(FILE_PREFIX.length);
7242
7572
  }
7243
7573
  }
7244
7574
  }
@@ -7345,7 +7675,7 @@ class UndefinedVariable extends Variable {
7345
7675
 
7346
7676
  class ExportDefaultVariable extends LocalVariable {
7347
7677
  constructor(name, exportDefaultDeclaration, context) {
7348
- super(name, exportDefaultDeclaration, exportDefaultDeclaration.declaration, context, 'other');
7678
+ super(name, exportDefaultDeclaration, exportDefaultDeclaration.declaration, EMPTY_PATH, context, 'other');
7349
7679
  this.hasId = false;
7350
7680
  this.originalId = null;
7351
7681
  this.originalVariable = null;
@@ -7494,8 +7824,8 @@ class NamespaceVariable extends Variable {
7494
7824
  return (!memberVariable ||
7495
7825
  memberVariable.hasEffectsOnInteractionAtPath(path.slice(1), interaction, context));
7496
7826
  }
7497
- include() {
7498
- super.include();
7827
+ includePath(path, context) {
7828
+ super.includePath(path, context);
7499
7829
  this.context.includeAllExports();
7500
7830
  }
7501
7831
  prepare(accessedGlobalsByScope) {
@@ -7588,9 +7918,9 @@ class SyntheticNamedExportVariable extends Variable {
7588
7918
  getName(getPropertyAccess) {
7589
7919
  return `${this.syntheticNamespace.getName(getPropertyAccess)}${getPropertyAccess(this.name)}`;
7590
7920
  }
7591
- include() {
7592
- super.include();
7593
- this.context.includeVariableInModule(this.syntheticNamespace);
7921
+ includePath(path, context) {
7922
+ super.includePath(path, context);
7923
+ this.context.includeVariableInModule(this.syntheticNamespace, path, context);
7594
7924
  }
7595
7925
  setRenderNames(baseName, name) {
7596
7926
  super.setRenderNames(baseName, name);
@@ -10789,21 +11119,37 @@ class ArrayPattern extends NodeBase {
10789
11119
  element?.addExportedVariables(variables, exportNamesByVariable);
10790
11120
  }
10791
11121
  }
10792
- declare(kind) {
11122
+ declare(kind, destructuredInitPath, init) {
10793
11123
  const variables = [];
11124
+ const includedPatternPath = getIncludedPatternPath(destructuredInitPath);
10794
11125
  for (const element of this.elements) {
10795
11126
  if (element !== null) {
10796
- variables.push(...element.declare(kind, UNKNOWN_EXPRESSION));
11127
+ variables.push(...element.declare(kind, includedPatternPath, init));
10797
11128
  }
10798
11129
  }
10799
11130
  return variables;
10800
11131
  }
11132
+ deoptimizeAssignment(destructuredInitPath, init) {
11133
+ const includedPatternPath = getIncludedPatternPath(destructuredInitPath);
11134
+ for (const element of this.elements) {
11135
+ element?.deoptimizeAssignment(includedPatternPath, init);
11136
+ }
11137
+ }
10801
11138
  // Patterns can only be deoptimized at the empty path at the moment
10802
11139
  deoptimizePath() {
10803
11140
  for (const element of this.elements) {
10804
11141
  element?.deoptimizePath(EMPTY_PATH);
10805
11142
  }
10806
11143
  }
11144
+ hasEffectsWhenDestructuring(context, destructuredInitPath, init) {
11145
+ const includedPatternPath = getIncludedPatternPath(destructuredInitPath);
11146
+ for (const element of this.elements) {
11147
+ if (element?.hasEffectsWhenDestructuring(context, includedPatternPath, init)) {
11148
+ return true;
11149
+ }
11150
+ }
11151
+ return false;
11152
+ }
10807
11153
  // Patterns are only checked at the empty path at the moment
10808
11154
  hasEffectsOnInteractionAtPath(_path, interaction, context) {
10809
11155
  for (const element of this.elements) {
@@ -10812,12 +11158,38 @@ class ArrayPattern extends NodeBase {
10812
11158
  }
10813
11159
  return false;
10814
11160
  }
11161
+ includeDestructuredIfNecessary(context, destructuredInitPath, init) {
11162
+ let included = false;
11163
+ const includedPatternPath = getIncludedPatternPath(destructuredInitPath);
11164
+ for (const element of this.elements) {
11165
+ if (element) {
11166
+ element.included ||= included;
11167
+ included =
11168
+ element.includeDestructuredIfNecessary(context, includedPatternPath, init) || included;
11169
+ }
11170
+ }
11171
+ if (included) {
11172
+ // This is necessary so that if any pattern element is included, all are
11173
+ // included for proper deconflicting
11174
+ for (const element of this.elements) {
11175
+ if (element && !element.included) {
11176
+ element.included = true;
11177
+ element.includeDestructuredIfNecessary(context, includedPatternPath, init);
11178
+ }
11179
+ }
11180
+ }
11181
+ return (this.included ||= included);
11182
+ }
10815
11183
  markDeclarationReached() {
10816
11184
  for (const element of this.elements) {
10817
11185
  element?.markDeclarationReached();
10818
11186
  }
10819
11187
  }
10820
11188
  }
11189
+ ArrayPattern.prototype.includeNode = onlyIncludeSelf;
11190
+ const getIncludedPatternPath = (destructuredInitPath) => destructuredInitPath.at(-1) === UnknownKey
11191
+ ? destructuredInitPath
11192
+ : [...destructuredInitPath, UnknownInteger];
10821
11193
 
10822
11194
  class ArrowFunctionExpression extends FunctionBase {
10823
11195
  constructor() {
@@ -10834,8 +11206,6 @@ class ArrowFunctionExpression extends FunctionBase {
10834
11206
  this.scope = new ReturnValueScope(parentScope, false);
10835
11207
  }
10836
11208
  hasEffects() {
10837
- if (!this.deoptimized)
10838
- this.applyDeoptimizations();
10839
11209
  return false;
10840
11210
  }
10841
11211
  hasEffectsOnInteractionAtPath(path, interaction, context) {
@@ -10874,6 +11244,15 @@ class ArrowFunctionExpression extends FunctionBase {
10874
11244
  }
10875
11245
  }
10876
11246
  }
11247
+ includeNode(context) {
11248
+ this.included = true;
11249
+ this.body.includePath(UNKNOWN_PATH, context);
11250
+ for (const parameter of this.params) {
11251
+ if (!(parameter instanceof Identifier)) {
11252
+ parameter.includePath(UNKNOWN_PATH, context);
11253
+ }
11254
+ }
11255
+ }
10877
11256
  getObjectEntity() {
10878
11257
  if (this.objectEntity !== null) {
10879
11258
  return this.objectEntity;
@@ -10893,13 +11272,18 @@ class ObjectPattern extends NodeBase {
10893
11272
  }
10894
11273
  }
10895
11274
  }
10896
- declare(kind, init) {
11275
+ declare(kind, destructuredInitPath, init) {
10897
11276
  const variables = [];
10898
11277
  for (const property of this.properties) {
10899
- variables.push(...property.declare(kind, init));
11278
+ variables.push(...property.declare(kind, destructuredInitPath, init));
10900
11279
  }
10901
11280
  return variables;
10902
11281
  }
11282
+ deoptimizeAssignment(destructuredInitPath, init) {
11283
+ for (const property of this.properties) {
11284
+ property.deoptimizeAssignment(destructuredInitPath, init);
11285
+ }
11286
+ }
10903
11287
  deoptimizePath(path) {
10904
11288
  if (path.length === 0) {
10905
11289
  for (const property of this.properties) {
@@ -10917,12 +11301,46 @@ class ObjectPattern extends NodeBase {
10917
11301
  }
10918
11302
  return false;
10919
11303
  }
11304
+ hasEffectsWhenDestructuring(context, destructuredInitPath, init) {
11305
+ for (const property of this.properties) {
11306
+ if (property.hasEffectsWhenDestructuring(context, destructuredInitPath, init))
11307
+ return true;
11308
+ }
11309
+ return false;
11310
+ }
11311
+ includeDestructuredIfNecessary(context, destructuredInitPath, init) {
11312
+ let included = false;
11313
+ for (const property of this.properties) {
11314
+ included =
11315
+ property.includeDestructuredIfNecessary(context, destructuredInitPath, init) || included;
11316
+ }
11317
+ return (this.included ||= included);
11318
+ }
10920
11319
  markDeclarationReached() {
10921
11320
  for (const property of this.properties) {
10922
11321
  property.markDeclarationReached();
10923
11322
  }
10924
11323
  }
11324
+ render(code, options) {
11325
+ if (this.properties.length > 0) {
11326
+ const separatedNodes = getCommaSeparatedNodesWithBoundaries(this.properties, code, this.start + 1, this.end - 1);
11327
+ let lastSeparatorPos = null;
11328
+ for (const { node, separator, start, end } of separatedNodes) {
11329
+ if (!node.included) {
11330
+ treeshakeNode(node, code, start, end);
11331
+ continue;
11332
+ }
11333
+ lastSeparatorPos = separator;
11334
+ node.render(code, options);
11335
+ }
11336
+ if (lastSeparatorPos) {
11337
+ code.remove(lastSeparatorPos, this.end - 1);
11338
+ }
11339
+ }
11340
+ }
10925
11341
  }
11342
+ ObjectPattern.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
11343
+ ObjectPattern.prototype.applyDeoptimizations = doNotDeoptimize;
10926
11344
 
10927
11345
  class AssignmentExpression extends NodeBase {
10928
11346
  hasEffects(context) {
@@ -10931,7 +11349,9 @@ class AssignmentExpression extends NodeBase {
10931
11349
  this.applyDeoptimizations();
10932
11350
  // MemberExpressions do not access the property before assignments if the
10933
11351
  // operator is '='.
10934
- return (right.hasEffects(context) || left.hasEffectsAsAssignmentTarget(context, operator !== '='));
11352
+ return (right.hasEffects(context) ||
11353
+ left.hasEffectsAsAssignmentTarget(context, operator !== '=') ||
11354
+ this.left.hasEffectsWhenDestructuring?.(context, EMPTY_PATH, right));
10935
11355
  }
10936
11356
  hasEffectsOnInteractionAtPath(path, interaction, context) {
10937
11357
  return this.right.hasEffectsOnInteractionAtPath(path, interaction, context);
@@ -10940,15 +11360,24 @@ class AssignmentExpression extends NodeBase {
10940
11360
  const { deoptimized, left, right, operator } = this;
10941
11361
  if (!deoptimized)
10942
11362
  this.applyDeoptimizations();
10943
- this.included = true;
11363
+ if (!this.included)
11364
+ this.includeNode(context);
11365
+ const hasEffectsContext = createHasEffectsContext();
10944
11366
  if (includeChildrenRecursively ||
10945
11367
  operator !== '=' ||
10946
11368
  left.included ||
10947
- left.hasEffectsAsAssignmentTarget(createHasEffectsContext(), false)) {
11369
+ left.hasEffectsAsAssignmentTarget(hasEffectsContext, false) ||
11370
+ left.hasEffectsWhenDestructuring?.(hasEffectsContext, EMPTY_PATH, right)) {
10948
11371
  left.includeAsAssignmentTarget(context, includeChildrenRecursively, operator !== '=');
10949
11372
  }
10950
11373
  right.include(context, includeChildrenRecursively);
10951
11374
  }
11375
+ includeNode(context) {
11376
+ this.included = true;
11377
+ if (!this.deoptimized)
11378
+ this.applyDeoptimizations();
11379
+ this.right.includePath(UNKNOWN_PATH, context);
11380
+ }
10952
11381
  initialise() {
10953
11382
  super.initialise();
10954
11383
  if (this.left instanceof Identifier) {
@@ -11009,8 +11438,7 @@ class AssignmentExpression extends NodeBase {
11009
11438
  }
11010
11439
  applyDeoptimizations() {
11011
11440
  this.deoptimized = true;
11012
- this.left.deoptimizePath(EMPTY_PATH);
11013
- this.right.deoptimizePath(UNKNOWN_PATH);
11441
+ this.left.deoptimizeAssignment(EMPTY_PATH, this.right);
11014
11442
  this.scope.context.requestTreeshakingPass();
11015
11443
  }
11016
11444
  }
@@ -11019,8 +11447,11 @@ class AssignmentPattern extends NodeBase {
11019
11447
  addExportedVariables(variables, exportNamesByVariable) {
11020
11448
  this.left.addExportedVariables(variables, exportNamesByVariable);
11021
11449
  }
11022
- declare(kind, init) {
11023
- return this.left.declare(kind, init);
11450
+ declare(kind, destructuredInitPath, init) {
11451
+ return this.left.declare(kind, destructuredInitPath, init);
11452
+ }
11453
+ deoptimizeAssignment(destructuredInitPath, init) {
11454
+ this.left.deoptimizeAssignment(destructuredInitPath, init);
11024
11455
  }
11025
11456
  deoptimizePath(path) {
11026
11457
  if (path.length === 0) {
@@ -11030,6 +11461,29 @@ class AssignmentPattern extends NodeBase {
11030
11461
  hasEffectsOnInteractionAtPath(path, interaction, context) {
11031
11462
  return (path.length > 0 || this.left.hasEffectsOnInteractionAtPath(EMPTY_PATH, interaction, context));
11032
11463
  }
11464
+ hasEffectsWhenDestructuring(context, destructuredInitPath, init) {
11465
+ return this.left.hasEffectsWhenDestructuring(context, destructuredInitPath, init);
11466
+ }
11467
+ includeDestructuredIfNecessary(context, destructuredInitPath, init) {
11468
+ let included = this.left.includeDestructuredIfNecessary(context, destructuredInitPath, init) ||
11469
+ this.included;
11470
+ if ((included ||= this.right.shouldBeIncluded(context))) {
11471
+ this.right.include(context, false);
11472
+ if (!this.left.included) {
11473
+ this.left.included = true;
11474
+ // Unfortunately, we need to include the left side again now, so that
11475
+ // any declared variables are properly included.
11476
+ this.left.includeDestructuredIfNecessary(context, destructuredInitPath, init);
11477
+ }
11478
+ }
11479
+ return (this.included = included);
11480
+ }
11481
+ includeNode(context) {
11482
+ this.included = true;
11483
+ if (!this.deoptimized)
11484
+ this.applyDeoptimizations();
11485
+ this.right.includePath(UNKNOWN_PATH, context);
11486
+ }
11033
11487
  markDeclarationReached() {
11034
11488
  this.left.markDeclarationReached();
11035
11489
  }
@@ -11052,22 +11506,34 @@ class AwaitExpression extends NodeBase {
11052
11506
  return true;
11053
11507
  }
11054
11508
  include(context, includeChildrenRecursively) {
11509
+ if (!this.included)
11510
+ this.includeNode(context);
11511
+ this.argument.include(context, includeChildrenRecursively);
11512
+ }
11513
+ includeNode(context) {
11514
+ this.included = true;
11055
11515
  if (!this.deoptimized)
11056
11516
  this.applyDeoptimizations();
11057
- if (!this.included) {
11058
- this.included = true;
11059
- checkTopLevelAwait: if (!this.scope.context.usesTopLevelAwait) {
11060
- let parent = this.parent;
11061
- do {
11062
- if (parent instanceof FunctionNode || parent instanceof ArrowFunctionExpression)
11063
- break checkTopLevelAwait;
11064
- } while ((parent = parent.parent));
11065
- this.scope.context.usesTopLevelAwait = true;
11066
- }
11517
+ checkTopLevelAwait: if (!this.scope.context.usesTopLevelAwait) {
11518
+ let parent = this.parent;
11519
+ do {
11520
+ if (parent instanceof FunctionNode || parent instanceof ArrowFunctionExpression)
11521
+ break checkTopLevelAwait;
11522
+ } while ((parent = parent.parent));
11523
+ this.scope.context.usesTopLevelAwait = true;
11067
11524
  }
11068
- this.argument.include(context, includeChildrenRecursively);
11525
+ // Thenables need to be included
11526
+ this.argument.includePath(THEN_PATH, context);
11527
+ }
11528
+ includePath(path, context) {
11529
+ if (!this.deoptimized)
11530
+ this.applyDeoptimizations();
11531
+ if (!this.included)
11532
+ this.includeNode(context);
11533
+ this.argument.includePath(path, context);
11069
11534
  }
11070
11535
  }
11536
+ const THEN_PATH = ['then'];
11071
11537
 
11072
11538
  const binaryOperators = {
11073
11539
  '!=': (left, right) => left != right,
@@ -11131,6 +11597,8 @@ class BinaryExpression extends NodeBase {
11131
11597
  this.right.render(code, options);
11132
11598
  }
11133
11599
  }
11600
+ BinaryExpression.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
11601
+ BinaryExpression.prototype.applyDeoptimizations = doNotDeoptimize;
11134
11602
 
11135
11603
  class BreakStatement extends NodeBase {
11136
11604
  hasEffects(context) {
@@ -11150,7 +11618,7 @@ class BreakStatement extends NodeBase {
11150
11618
  include(context) {
11151
11619
  this.included = true;
11152
11620
  if (this.label) {
11153
- this.label.include();
11621
+ this.label.include(context);
11154
11622
  context.includedLabels.add(this.label.name);
11155
11623
  }
11156
11624
  else {
@@ -11159,6 +11627,8 @@ class BreakStatement extends NodeBase {
11159
11627
  context.brokenFlow = true;
11160
11628
  }
11161
11629
  }
11630
+ BreakStatement.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
11631
+ BreakStatement.prototype.applyDeoptimizations = doNotDeoptimize;
11162
11632
 
11163
11633
  function renderCallArguments(code, options, node) {
11164
11634
  if (node.arguments.length > 0) {
@@ -11345,8 +11815,6 @@ class CallExpression extends CallExpressionBase {
11345
11815
  this.callee.hasEffectsOnInteractionAtPath(EMPTY_PATH, this.interaction, context)));
11346
11816
  }
11347
11817
  include(context, includeChildrenRecursively) {
11348
- if (!this.deoptimized)
11349
- this.applyDeoptimizations();
11350
11818
  if (includeChildrenRecursively) {
11351
11819
  super.include(context, includeChildrenRecursively);
11352
11820
  if (includeChildrenRecursively === INCLUDE_PARAMETERS &&
@@ -11356,10 +11824,26 @@ class CallExpression extends CallExpressionBase {
11356
11824
  }
11357
11825
  }
11358
11826
  else {
11359
- this.included = true;
11360
- this.callee.include(context, false);
11827
+ if (!this.included)
11828
+ this.includeNode(context);
11829
+ // If the callee is a member expression and does not have a variable, its
11830
+ // object will already be included via the first argument of the
11831
+ // interaction in includeCallArguments. Including it again can lead to
11832
+ // severe performance problems.
11833
+ if (this.callee instanceof MemberExpression && !this.callee.variable) {
11834
+ this.callee.property.include(context, false);
11835
+ }
11836
+ else {
11837
+ this.callee.include(context, false);
11838
+ }
11839
+ this.callee.includeCallArguments(context, this.interaction);
11361
11840
  }
11362
- this.callee.includeCallArguments(context, this.arguments);
11841
+ }
11842
+ includeNode(context) {
11843
+ this.included = true;
11844
+ if (!this.deoptimized)
11845
+ this.applyDeoptimizations();
11846
+ this.callee.includePath(UNKNOWN_PATH, context);
11363
11847
  }
11364
11848
  initialise() {
11365
11849
  super.initialise();
@@ -11398,13 +11882,14 @@ class CatchClause extends NodeBase {
11398
11882
  this.type = type;
11399
11883
  if (param) {
11400
11884
  this.param = new (this.scope.context.getNodeConstructor(param.type))(this, this.scope).parseNode(param);
11401
- this.param.declare('parameter', UNKNOWN_EXPRESSION);
11885
+ this.param.declare('parameter', EMPTY_PATH, UNKNOWN_EXPRESSION);
11402
11886
  }
11403
11887
  this.body = new BlockStatement(this, this.scope.bodyScope).parseNode(body);
11404
11888
  return super.parseNode(esTreeNode);
11405
11889
  }
11406
11890
  }
11407
11891
  CatchClause.prototype.preventChildBlockScope = true;
11892
+ CatchClause.prototype.includeNode = onlyIncludeSelf;
11408
11893
 
11409
11894
  class ChainExpression extends NodeBase {
11410
11895
  // deoptimizations are not relevant as we are not caching values
@@ -11416,17 +11901,22 @@ class ChainExpression extends NodeBase {
11416
11901
  hasEffects(context) {
11417
11902
  return this.expression.hasEffectsAsChainElement(context) === true;
11418
11903
  }
11904
+ includePath(path, context) {
11905
+ this.included = true;
11906
+ this.expression.includePath(path, context);
11907
+ }
11419
11908
  removeAnnotations(code) {
11420
11909
  this.expression.removeAnnotations(code);
11421
11910
  }
11422
- applyDeoptimizations() { }
11423
11911
  }
11912
+ ChainExpression.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
11913
+ ChainExpression.prototype.applyDeoptimizations = doNotDeoptimize;
11424
11914
 
11425
11915
  class ClassBodyScope extends ChildScope {
11426
11916
  constructor(parent, classNode) {
11427
11917
  const { context } = parent;
11428
11918
  super(parent, context);
11429
- this.variables.set('this', (this.thisVariable = new LocalVariable('this', null, classNode, context, 'other')));
11919
+ this.variables.set('this', (this.thisVariable = new LocalVariable('this', null, classNode, EMPTY_PATH, context, 'other')));
11430
11920
  this.instanceScope = new ChildScope(this, context);
11431
11921
  this.instanceScope.variables.set('this', new ThisVariable(context));
11432
11922
  }
@@ -11441,7 +11931,7 @@ class ClassBody extends NodeBase {
11441
11931
  }
11442
11932
  include(context, includeChildrenRecursively) {
11443
11933
  this.included = true;
11444
- this.scope.context.includeVariableInModule(this.scope.thisVariable);
11934
+ this.scope.context.includeVariableInModule(this.scope.thisVariable, UNKNOWN_PATH, context);
11445
11935
  for (const definition of this.body) {
11446
11936
  definition.include(context, includeChildrenRecursively);
11447
11937
  }
@@ -11454,8 +11944,9 @@ class ClassBody extends NodeBase {
11454
11944
  }
11455
11945
  return super.parseNode(esTreeNode);
11456
11946
  }
11457
- applyDeoptimizations() { }
11458
11947
  }
11948
+ ClassBody.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
11949
+ ClassBody.prototype.applyDeoptimizations = doNotDeoptimize;
11459
11950
 
11460
11951
  class ClassExpression extends ClassNode {
11461
11952
  render(code, options, { renderedSurroundingElement } = BLANK) {
@@ -11513,6 +12004,9 @@ class ConditionalExpression extends NodeBase {
11513
12004
  const unusedBranch = this.usedBranch === this.consequent ? this.alternate : this.consequent;
11514
12005
  this.usedBranch = null;
11515
12006
  unusedBranch.deoptimizePath(UNKNOWN_PATH);
12007
+ if (this.included) {
12008
+ unusedBranch.includePath(UNKNOWN_PATH, createInclusionContext());
12009
+ }
11516
12010
  const { expressionsToBeDeoptimized } = this;
11517
12011
  this.expressionsToBeDeoptimized = EMPTY_ARRAY;
11518
12012
  for (const expression of expressionsToBeDeoptimized) {
@@ -11570,7 +12064,7 @@ class ConditionalExpression extends NodeBase {
11570
12064
  include(context, includeChildrenRecursively) {
11571
12065
  this.included = true;
11572
12066
  const usedBranch = this.getUsedBranch();
11573
- if (includeChildrenRecursively || this.test.shouldBeIncluded(context) || usedBranch === null) {
12067
+ if (usedBranch === null || includeChildrenRecursively || this.test.shouldBeIncluded(context)) {
11574
12068
  this.test.include(context, includeChildrenRecursively);
11575
12069
  this.consequent.include(context, includeChildrenRecursively);
11576
12070
  this.alternate.include(context, includeChildrenRecursively);
@@ -11579,27 +12073,38 @@ class ConditionalExpression extends NodeBase {
11579
12073
  usedBranch.include(context, includeChildrenRecursively);
11580
12074
  }
11581
12075
  }
11582
- includeCallArguments(context, parameters) {
12076
+ includePath(path, context) {
12077
+ this.included = true;
12078
+ const usedBranch = this.getUsedBranch();
12079
+ if (usedBranch === null || this.test.shouldBeIncluded(context)) {
12080
+ this.consequent.includePath(path, context);
12081
+ this.alternate.includePath(path, context);
12082
+ }
12083
+ else {
12084
+ usedBranch.includePath(path, context);
12085
+ }
12086
+ }
12087
+ includeCallArguments(context, interaction) {
11583
12088
  const usedBranch = this.getUsedBranch();
11584
12089
  if (usedBranch) {
11585
- usedBranch.includeCallArguments(context, parameters);
12090
+ usedBranch.includeCallArguments(context, interaction);
11586
12091
  }
11587
12092
  else {
11588
- this.consequent.includeCallArguments(context, parameters);
11589
- this.alternate.includeCallArguments(context, parameters);
12093
+ this.consequent.includeCallArguments(context, interaction);
12094
+ this.alternate.includeCallArguments(context, interaction);
11590
12095
  }
11591
12096
  }
11592
12097
  removeAnnotations(code) {
11593
12098
  this.test.removeAnnotations(code);
11594
12099
  }
11595
12100
  render(code, options, { isCalleeOfRenderedParent, preventASI, renderedParentType, renderedSurroundingElement } = BLANK) {
11596
- const usedBranch = this.getUsedBranch();
11597
12101
  if (this.test.included) {
11598
12102
  this.test.render(code, options, { renderedSurroundingElement });
11599
12103
  this.consequent.render(code, options);
11600
12104
  this.alternate.render(code, options);
11601
12105
  }
11602
12106
  else {
12107
+ const usedBranch = this.getUsedBranch();
11603
12108
  const colonPos = findFirstOccurrenceOutsideComment(code.original, ':', this.consequent.end);
11604
12109
  const inclusionStart = findNonWhiteSpace(code.original, (this.consequent.included
11605
12110
  ? findFirstOccurrenceOutsideComment(code.original, '?', this.test.end)
@@ -11631,6 +12136,8 @@ class ConditionalExpression extends NodeBase {
11631
12136
  : (this.usedBranch = testValue ? this.consequent : this.alternate);
11632
12137
  }
11633
12138
  }
12139
+ ConditionalExpression.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
12140
+ ConditionalExpression.prototype.applyDeoptimizations = doNotDeoptimize;
11634
12141
 
11635
12142
  class ContinueStatement extends NodeBase {
11636
12143
  hasEffects(context) {
@@ -11650,7 +12157,7 @@ class ContinueStatement extends NodeBase {
11650
12157
  include(context) {
11651
12158
  this.included = true;
11652
12159
  if (this.label) {
11653
- this.label.include();
12160
+ this.label.include(context);
11654
12161
  context.includedLabels.add(this.label.name);
11655
12162
  }
11656
12163
  else {
@@ -11659,12 +12166,15 @@ class ContinueStatement extends NodeBase {
11659
12166
  context.brokenFlow = true;
11660
12167
  }
11661
12168
  }
12169
+ ContinueStatement.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
12170
+ ContinueStatement.prototype.applyDeoptimizations = doNotDeoptimize;
11662
12171
 
11663
12172
  class DebuggerStatement extends NodeBase {
11664
12173
  hasEffects() {
11665
12174
  return true;
11666
12175
  }
11667
12176
  }
12177
+ DebuggerStatement.prototype.includeNode = onlyIncludeSelf;
11668
12178
 
11669
12179
  class Decorator extends NodeBase {
11670
12180
  hasEffects(context) {
@@ -11672,6 +12182,7 @@ class Decorator extends NodeBase {
11672
12182
  this.expression.hasEffectsOnInteractionAtPath(EMPTY_PATH, NODE_INTERACTION_UNKNOWN_CALL, context));
11673
12183
  }
11674
12184
  }
12185
+ Decorator.prototype.includeNode = onlyIncludeSelf;
11675
12186
 
11676
12187
  function hasLoopBodyEffects(context, body) {
11677
12188
  const { brokenFlow, hasBreak, hasContinue, ignore } = context;
@@ -11711,12 +12222,15 @@ class DoWhileStatement extends NodeBase {
11711
12222
  includeLoopBody(context, this.body, includeChildrenRecursively);
11712
12223
  }
11713
12224
  }
12225
+ DoWhileStatement.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
12226
+ DoWhileStatement.prototype.applyDeoptimizations = doNotDeoptimize;
11714
12227
 
11715
12228
  class EmptyStatement extends NodeBase {
11716
12229
  hasEffects() {
11717
12230
  return false;
11718
12231
  }
11719
12232
  }
12233
+ EmptyStatement.prototype.includeNode = onlyIncludeSelf;
11720
12234
 
11721
12235
  class ExportAllDeclaration extends NodeBase {
11722
12236
  hasEffects() {
@@ -11729,9 +12243,10 @@ class ExportAllDeclaration extends NodeBase {
11729
12243
  render(code, _options, nodeRenderOptions) {
11730
12244
  code.remove(nodeRenderOptions.start, nodeRenderOptions.end);
11731
12245
  }
11732
- applyDeoptimizations() { }
11733
12246
  }
11734
12247
  ExportAllDeclaration.prototype.needsBoundaries = true;
12248
+ ExportAllDeclaration.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
12249
+ ExportAllDeclaration.prototype.applyDeoptimizations = doNotDeoptimize;
11735
12250
 
11736
12251
  class ExportNamedDeclaration extends NodeBase {
11737
12252
  bind() {
@@ -11758,13 +12273,15 @@ class ExportNamedDeclaration extends NodeBase {
11758
12273
  this.declaration.render(code, options, { end, start });
11759
12274
  }
11760
12275
  }
11761
- applyDeoptimizations() { }
11762
12276
  }
11763
12277
  ExportNamedDeclaration.prototype.needsBoundaries = true;
12278
+ ExportNamedDeclaration.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
12279
+ ExportNamedDeclaration.prototype.applyDeoptimizations = doNotDeoptimize;
11764
12280
 
11765
12281
  class ExportSpecifier extends NodeBase {
11766
- applyDeoptimizations() { }
11767
12282
  }
12283
+ ExportSpecifier.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
12284
+ ExportSpecifier.prototype.applyDeoptimizations = doNotDeoptimize;
11768
12285
 
11769
12286
  class ForInStatement extends NodeBase {
11770
12287
  createScope(parentScope) {
@@ -11782,11 +12299,18 @@ class ForInStatement extends NodeBase {
11782
12299
  const { body, deoptimized, left, right } = this;
11783
12300
  if (!deoptimized)
11784
12301
  this.applyDeoptimizations();
11785
- this.included = true;
12302
+ if (!this.included)
12303
+ this.includeNode(context);
11786
12304
  left.includeAsAssignmentTarget(context, includeChildrenRecursively || true, false);
11787
12305
  right.include(context, includeChildrenRecursively);
11788
12306
  includeLoopBody(context, body, includeChildrenRecursively);
11789
12307
  }
12308
+ includeNode(context) {
12309
+ this.included = true;
12310
+ if (!this.deoptimized)
12311
+ this.applyDeoptimizations();
12312
+ this.right.includePath(UNKNOWN_PATH, context);
12313
+ }
11790
12314
  initialise() {
11791
12315
  super.initialise();
11792
12316
  this.left.setAssignedValue(UNKNOWN_EXPRESSION);
@@ -11827,11 +12351,18 @@ class ForOfStatement extends NodeBase {
11827
12351
  const { body, deoptimized, left, right } = this;
11828
12352
  if (!deoptimized)
11829
12353
  this.applyDeoptimizations();
11830
- this.included = true;
12354
+ if (!this.included)
12355
+ this.includeNode(context);
11831
12356
  left.includeAsAssignmentTarget(context, includeChildrenRecursively || true, false);
11832
12357
  right.include(context, includeChildrenRecursively);
11833
12358
  includeLoopBody(context, body, includeChildrenRecursively);
11834
12359
  }
12360
+ includeNode(context) {
12361
+ this.included = true;
12362
+ if (!this.deoptimized)
12363
+ this.applyDeoptimizations();
12364
+ this.right.includePath(UNKNOWN_PATH, context);
12365
+ }
11835
12366
  initialise() {
11836
12367
  super.initialise();
11837
12368
  this.left.setAssignedValue(UNKNOWN_EXPRESSION);
@@ -11867,7 +12398,9 @@ class ForStatement extends NodeBase {
11867
12398
  }
11868
12399
  include(context, includeChildrenRecursively) {
11869
12400
  this.included = true;
11870
- this.init?.include(context, includeChildrenRecursively, { asSingleStatement: true });
12401
+ this.init?.include(context, includeChildrenRecursively, {
12402
+ asSingleStatement: true
12403
+ });
11871
12404
  this.test?.include(context, includeChildrenRecursively);
11872
12405
  this.update?.include(context, includeChildrenRecursively);
11873
12406
  includeLoopBody(context, this.body, includeChildrenRecursively);
@@ -11879,6 +12412,8 @@ class ForStatement extends NodeBase {
11879
12412
  this.body.render(code, options);
11880
12413
  }
11881
12414
  }
12415
+ ForStatement.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
12416
+ ForStatement.prototype.applyDeoptimizations = doNotDeoptimize;
11882
12417
 
11883
12418
  class FunctionExpression extends FunctionNode {
11884
12419
  createScope(parentScope) {
@@ -11910,9 +12445,9 @@ class TrackingScope extends BlockScope {
11910
12445
  super(...arguments);
11911
12446
  this.hoistedDeclarations = [];
11912
12447
  }
11913
- addDeclaration(identifier, context, init, kind) {
12448
+ addDeclaration(identifier, context, init, destructuredInitPath, kind) {
11914
12449
  this.hoistedDeclarations.push(identifier);
11915
- return super.addDeclaration(identifier, context, init, kind);
12450
+ return super.addDeclaration(identifier, context, init, destructuredInitPath, kind);
11916
12451
  }
11917
12452
  }
11918
12453
 
@@ -12011,7 +12546,6 @@ class IfStatement extends NodeBase {
12011
12546
  }
12012
12547
  this.renderHoistedDeclarations(hoistedDeclarations, code, getPropertyAccess);
12013
12548
  }
12014
- applyDeoptimizations() { }
12015
12549
  getTestValue() {
12016
12550
  if (this.testValue === unset) {
12017
12551
  return (this.testValue = this.test.getLiteralValueAtPath(EMPTY_PATH, SHARED_RECURSION_TRACKER, this));
@@ -12080,6 +12614,8 @@ class IfStatement extends NodeBase {
12080
12614
  return false;
12081
12615
  }
12082
12616
  }
12617
+ IfStatement.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
12618
+ IfStatement.prototype.applyDeoptimizations = doNotDeoptimize;
12083
12619
 
12084
12620
  class ImportAttribute extends NodeBase {
12085
12621
  }
@@ -12097,13 +12633,15 @@ class ImportDeclaration extends NodeBase {
12097
12633
  render(code, _options, nodeRenderOptions) {
12098
12634
  code.remove(nodeRenderOptions.start, nodeRenderOptions.end);
12099
12635
  }
12100
- applyDeoptimizations() { }
12101
12636
  }
12102
12637
  ImportDeclaration.prototype.needsBoundaries = true;
12638
+ ImportDeclaration.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
12639
+ ImportDeclaration.prototype.applyDeoptimizations = doNotDeoptimize;
12103
12640
 
12104
12641
  class ImportDefaultSpecifier extends NodeBase {
12105
- applyDeoptimizations() { }
12106
12642
  }
12643
+ ImportDefaultSpecifier.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
12644
+ ImportDefaultSpecifier.prototype.applyDeoptimizations = doNotDeoptimize;
12107
12645
 
12108
12646
  function isReassignedExportsMember(variable, exportNamesByVariable) {
12109
12647
  return (variable.renderBaseName !== null && exportNamesByVariable.has(variable) && variable.isReassigned);
@@ -12112,28 +12650,33 @@ function isReassignedExportsMember(variable, exportNamesByVariable) {
12112
12650
  class VariableDeclarator extends NodeBase {
12113
12651
  declareDeclarator(kind, isUsingDeclaration) {
12114
12652
  this.isUsingDeclaration = isUsingDeclaration;
12115
- this.id.declare(kind, this.init || UNDEFINED_EXPRESSION);
12653
+ this.id.declare(kind, EMPTY_PATH, this.init || UNDEFINED_EXPRESSION);
12116
12654
  }
12117
12655
  deoptimizePath(path) {
12118
12656
  this.id.deoptimizePath(path);
12119
12657
  }
12120
12658
  hasEffects(context) {
12121
- if (!this.deoptimized)
12122
- this.applyDeoptimizations();
12123
12659
  const initEffect = this.init?.hasEffects(context);
12124
12660
  this.id.markDeclarationReached();
12125
- return initEffect || this.id.hasEffects(context) || this.isUsingDeclaration;
12661
+ return (initEffect ||
12662
+ this.isUsingDeclaration ||
12663
+ this.id.hasEffects(context) ||
12664
+ (this.scope.context.options.treeshake
12665
+ .propertyReadSideEffects &&
12666
+ this.id.hasEffectsWhenDestructuring(context, EMPTY_PATH, this.init || UNDEFINED_EXPRESSION)));
12126
12667
  }
12127
12668
  include(context, includeChildrenRecursively) {
12128
- const { deoptimized, id, init } = this;
12129
- if (!deoptimized)
12130
- this.applyDeoptimizations();
12131
- this.included = true;
12669
+ const { id, init } = this;
12670
+ if (!this.included)
12671
+ this.includeNode();
12132
12672
  init?.include(context, includeChildrenRecursively);
12133
12673
  id.markDeclarationReached();
12134
- if (includeChildrenRecursively || id.shouldBeIncluded(context)) {
12674
+ if (includeChildrenRecursively) {
12135
12675
  id.include(context, includeChildrenRecursively);
12136
12676
  }
12677
+ else {
12678
+ id.includeDestructuredIfNecessary(context, EMPTY_PATH, init || UNDEFINED_EXPRESSION);
12679
+ }
12137
12680
  }
12138
12681
  removeAnnotations(code) {
12139
12682
  this.init?.removeAnnotations(code);
@@ -12163,8 +12706,8 @@ class VariableDeclarator extends NodeBase {
12163
12706
  code.appendLeft(end, `${_}=${_}void 0`);
12164
12707
  }
12165
12708
  }
12166
- applyDeoptimizations() {
12167
- this.deoptimized = true;
12709
+ includeNode() {
12710
+ this.included = true;
12168
12711
  const { id, init } = this;
12169
12712
  if (init && id instanceof Identifier && init instanceof ClassExpression && !init.id) {
12170
12713
  const { name, variable } = id;
@@ -12176,11 +12719,14 @@ class VariableDeclarator extends NodeBase {
12176
12719
  }
12177
12720
  }
12178
12721
  }
12722
+ VariableDeclarator.prototype.applyDeoptimizations = doNotDeoptimize;
12179
12723
 
12180
12724
  class ImportExpression extends NodeBase {
12181
12725
  constructor() {
12182
12726
  super(...arguments);
12183
12727
  this.inlineNamespace = null;
12728
+ this.hasUnknownAccessedKey = false;
12729
+ this.accessedPropKey = new Set();
12184
12730
  this.attributes = null;
12185
12731
  this.mechanism = null;
12186
12732
  this.namespaceExportName = undefined;
@@ -12213,12 +12759,15 @@ class ImportExpression extends NodeBase {
12213
12759
  if (parent2 instanceof ExpressionStatement) {
12214
12760
  return EMPTY_ARRAY;
12215
12761
  }
12216
- // Case 1: const { foo } = await import('bar')
12762
+ // Case 1: const { foo } / module = await import('bar')
12217
12763
  if (parent2 instanceof VariableDeclarator) {
12218
12764
  const declaration = parent2.id;
12219
- return declaration instanceof ObjectPattern
12220
- ? getDeterministicObjectDestructure(declaration)
12221
- : undefined;
12765
+ if (declaration instanceof Identifier) {
12766
+ return this.hasUnknownAccessedKey ? undefined : [...this.accessedPropKey];
12767
+ }
12768
+ if (declaration instanceof ObjectPattern) {
12769
+ return getDeterministicObjectDestructure(declaration);
12770
+ }
12222
12771
  }
12223
12772
  // Case 2: (await import('bar')).foo
12224
12773
  if (parent2 instanceof MemberExpression) {
@@ -12268,13 +12817,30 @@ class ImportExpression extends NodeBase {
12268
12817
  return true;
12269
12818
  }
12270
12819
  include(context, includeChildrenRecursively) {
12271
- if (!this.included) {
12272
- this.included = true;
12273
- this.scope.context.includeDynamicImport(this);
12274
- this.scope.addAccessedDynamicImport(this);
12275
- }
12820
+ if (!this.included)
12821
+ this.includeNode();
12276
12822
  this.source.include(context, includeChildrenRecursively);
12277
12823
  }
12824
+ includeNode() {
12825
+ this.included = true;
12826
+ this.scope.context.includeDynamicImport(this);
12827
+ this.scope.addAccessedDynamicImport(this);
12828
+ }
12829
+ includePath(path) {
12830
+ if (!this.included)
12831
+ this.includeNode();
12832
+ // Technically, this is not correct as dynamic imports return a Promise.
12833
+ if (this.hasUnknownAccessedKey)
12834
+ return;
12835
+ if (path[0] === UnknownKey) {
12836
+ this.hasUnknownAccessedKey = true;
12837
+ }
12838
+ else if (typeof path[0] === 'string') {
12839
+ this.accessedPropKey.add(path[0]);
12840
+ }
12841
+ // Update included paths
12842
+ this.scope.context.includeDynamicImport(this);
12843
+ }
12278
12844
  initialise() {
12279
12845
  super.initialise();
12280
12846
  this.scope.context.addDynamicImport(this);
@@ -12343,7 +12909,6 @@ class ImportExpression extends NodeBase {
12343
12909
  setInternalResolution(inlineNamespace) {
12344
12910
  this.inlineNamespace = inlineNamespace;
12345
12911
  }
12346
- applyDeoptimizations() { }
12347
12912
  getDynamicImportMechanismAndHelper(resolution, exportMode, { compact, dynamicImportInCjs, format, generatedCode: { arrowFunctions }, interop }, { _, getDirectReturnFunction, getDirectReturnIifeLeft }, pluginDriver) {
12348
12913
  const mechanism = pluginDriver.hookFirstSync('renderDynamicImport', [
12349
12914
  {
@@ -12433,6 +12998,7 @@ class ImportExpression extends NodeBase {
12433
12998
  return { helper: null, mechanism: null };
12434
12999
  }
12435
13000
  }
13001
+ ImportExpression.prototype.applyDeoptimizations = doNotDeoptimize;
12436
13002
  function getInteropHelper(resolution, exportMode, interop) {
12437
13003
  return exportMode === 'external'
12438
13004
  ? namespaceInteropHelpersByInteropType[interop(resolution instanceof ExternalModule ? resolution.id : null)]
@@ -12456,12 +13022,14 @@ function getDeterministicObjectDestructure(objectPattern) {
12456
13022
  }
12457
13023
 
12458
13024
  class ImportNamespaceSpecifier extends NodeBase {
12459
- applyDeoptimizations() { }
12460
13025
  }
13026
+ ImportNamespaceSpecifier.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
13027
+ ImportNamespaceSpecifier.prototype.applyDeoptimizations = doNotDeoptimize;
12461
13028
 
12462
13029
  class ImportSpecifier extends NodeBase {
12463
- applyDeoptimizations() { }
12464
13030
  }
13031
+ ImportSpecifier.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
13032
+ ImportSpecifier.prototype.applyDeoptimizations = doNotDeoptimize;
12465
13033
 
12466
13034
  class JSXIdentifier extends IdentifierBase {
12467
13035
  constructor() {
@@ -12478,6 +13046,29 @@ class JSXIdentifier extends IdentifierBase {
12478
13046
  this.isNativeElement = true;
12479
13047
  }
12480
13048
  }
13049
+ include(context) {
13050
+ if (!this.included)
13051
+ this.includeNode(context);
13052
+ }
13053
+ includeNode(context) {
13054
+ this.included = true;
13055
+ if (!this.deoptimized)
13056
+ this.applyDeoptimizations();
13057
+ if (this.variable !== null) {
13058
+ this.scope.context.includeVariableInModule(this.variable, EMPTY_PATH, context);
13059
+ }
13060
+ }
13061
+ includePath(path, context) {
13062
+ if (!this.included) {
13063
+ this.included = true;
13064
+ if (this.variable !== null) {
13065
+ this.scope.context.includeVariableInModule(this.variable, path, context);
13066
+ }
13067
+ }
13068
+ else if (path.length > 0) {
13069
+ this.variable?.includePath(path, context);
13070
+ }
13071
+ }
12481
13072
  render(code, { snippets: { getPropertyAccess }, useOriginalName }) {
12482
13073
  if (this.variable) {
12483
13074
  const name = this.variable.getName(getPropertyAccess, useOriginalName);
@@ -12539,6 +13130,7 @@ class JSXAttribute extends NodeBase {
12539
13130
  }
12540
13131
  }
12541
13132
  }
13133
+ JSXAttribute.prototype.includeNode = onlyIncludeSelf;
12542
13134
 
12543
13135
  class JSXClosingBase extends NodeBase {
12544
13136
  render(code, options) {
@@ -12551,6 +13143,7 @@ class JSXClosingBase extends NodeBase {
12551
13143
  }
12552
13144
  }
12553
13145
  }
13146
+ JSXClosingBase.prototype.includeNode = onlyIncludeSelf;
12554
13147
 
12555
13148
  class JSXClosingElement extends JSXClosingBase {
12556
13149
  }
@@ -12571,8 +13164,15 @@ class JSXSpreadAttribute extends NodeBase {
12571
13164
 
12572
13165
  class JSXEmptyExpression extends NodeBase {
12573
13166
  }
13167
+ JSXEmptyExpression.prototype.includeNode = onlyIncludeSelf;
12574
13168
 
12575
13169
  class JSXExpressionContainer extends NodeBase {
13170
+ includeNode(context) {
13171
+ this.included = true;
13172
+ if (!this.deoptimized)
13173
+ this.applyDeoptimizations();
13174
+ this.expression.includePath(UNKNOWN_PATH, context);
13175
+ }
12576
13176
  render(code, options) {
12577
13177
  const { mode } = this.scope.context.options.jsx;
12578
13178
  if (mode !== 'preserve') {
@@ -12593,7 +13193,7 @@ function getRenderedJsxChildren(children) {
12593
13193
  return renderedChildren;
12594
13194
  }
12595
13195
 
12596
- function getAndIncludeFactoryVariable(factory, preserve, importSource, node) {
13196
+ function getAndIncludeFactoryVariable(factory, preserve, importSource, node, context) {
12597
13197
  const [baseName, nestedName] = factory.split('.');
12598
13198
  let factoryVariable;
12599
13199
  if (importSource) {
@@ -12601,7 +13201,7 @@ function getAndIncludeFactoryVariable(factory, preserve, importSource, node) {
12601
13201
  if (preserve) {
12602
13202
  // This pretends we are accessing an included global variable of the same name
12603
13203
  const globalVariable = node.scope.findGlobal(baseName);
12604
- globalVariable.include();
13204
+ globalVariable.includePath(UNKNOWN_PATH, context);
12605
13205
  // This excludes this variable from renaming
12606
13206
  factoryVariable.globalName = baseName;
12607
13207
  }
@@ -12609,7 +13209,7 @@ function getAndIncludeFactoryVariable(factory, preserve, importSource, node) {
12609
13209
  else {
12610
13210
  factoryVariable = node.scope.findGlobal(baseName);
12611
13211
  }
12612
- node.scope.context.includeVariableInModule(factoryVariable);
13212
+ node.scope.context.includeVariableInModule(factoryVariable, UNKNOWN_PATH, context);
12613
13213
  if (factoryVariable instanceof LocalVariable) {
12614
13214
  factoryVariable.consolidateInitializers();
12615
13215
  factoryVariable.addUsedPlace(node);
@@ -12632,16 +13232,20 @@ class JSXElementBase extends NodeBase {
12632
13232
  }
12633
13233
  }
12634
13234
  include(context, includeChildrenRecursively) {
12635
- if (!this.included) {
12636
- const { factory, importSource, mode } = this.jsxMode;
12637
- if (factory) {
12638
- this.factory = factory;
12639
- this.factoryVariable = getAndIncludeFactoryVariable(factory, mode === 'preserve', importSource, this);
12640
- }
13235
+ if (!this.included)
13236
+ this.includeNode(context);
13237
+ for (const child of this.children) {
13238
+ child.include(context, includeChildrenRecursively);
13239
+ }
13240
+ }
13241
+ includeNode(context) {
13242
+ this.included = true;
13243
+ const { factory, importSource, mode } = this.jsxMode;
13244
+ if (factory) {
13245
+ this.factory = factory;
13246
+ this.factoryVariable = getAndIncludeFactoryVariable(factory, mode === 'preserve', importSource, this, context);
12641
13247
  }
12642
- super.include(context, includeChildrenRecursively);
12643
13248
  }
12644
- applyDeoptimizations() { }
12645
13249
  getRenderingMode() {
12646
13250
  const jsx = this.scope.context.options.jsx;
12647
13251
  const { mode, factory, importSource } = jsx;
@@ -12679,8 +13283,14 @@ class JSXElementBase extends NodeBase {
12679
13283
  return { childrenEnd, firstChild, hasMultipleChildren };
12680
13284
  }
12681
13285
  }
13286
+ JSXElementBase.prototype.applyDeoptimizations = doNotDeoptimize;
12682
13287
 
12683
13288
  class JSXElement extends JSXElementBase {
13289
+ include(context, includeChildrenRecursively) {
13290
+ super.include(context, includeChildrenRecursively);
13291
+ this.openingElement.include(context, includeChildrenRecursively);
13292
+ this.closingElement?.include(context, includeChildrenRecursively);
13293
+ }
12684
13294
  render(code, options) {
12685
13295
  switch (this.jsxMode.mode) {
12686
13296
  case 'classic': {
@@ -12832,6 +13442,11 @@ class JSXElement extends JSXElementBase {
12832
13442
  }
12833
13443
 
12834
13444
  class JSXFragment extends JSXElementBase {
13445
+ include(context, includeChildrenRecursively) {
13446
+ super.include(context, includeChildrenRecursively);
13447
+ this.openingFragment.include(context, includeChildrenRecursively);
13448
+ this.closingFragment.include(context, includeChildrenRecursively);
13449
+ }
12835
13450
  render(code, options) {
12836
13451
  switch (this.jsxMode.mode) {
12837
13452
  case 'classic': {
@@ -12881,10 +13496,22 @@ class JSXFragment extends JSXElementBase {
12881
13496
  }
12882
13497
 
12883
13498
  class JSXMemberExpression extends NodeBase {
13499
+ includeNode(context) {
13500
+ this.included = true;
13501
+ if (!this.deoptimized)
13502
+ this.applyDeoptimizations();
13503
+ this.object.includePath([this.property.name], context);
13504
+ }
13505
+ includePath(path, context) {
13506
+ if (!this.included)
13507
+ this.includeNode(context);
13508
+ this.object.includePath([this.property.name, ...path], context);
13509
+ }
12884
13510
  }
12885
13511
 
12886
13512
  class JSXNamespacedName extends NodeBase {
12887
13513
  }
13514
+ JSXNamespacedName.prototype.includeNode = onlyIncludeSelf;
12888
13515
 
12889
13516
  class JSXOpeningElement extends NodeBase {
12890
13517
  render(code, options, { jsxMode = this.scope.context.options.jsx.mode } = {}) {
@@ -12894,6 +13521,7 @@ class JSXOpeningElement extends NodeBase {
12894
13521
  }
12895
13522
  }
12896
13523
  }
13524
+ JSXOpeningElement.prototype.includeNode = onlyIncludeSelf;
12897
13525
 
12898
13526
  class JSXOpeningFragment extends NodeBase {
12899
13527
  constructor() {
@@ -12901,22 +13529,22 @@ class JSXOpeningFragment extends NodeBase {
12901
13529
  this.fragment = null;
12902
13530
  this.fragmentVariable = null;
12903
13531
  }
12904
- include(context, includeChildrenRecursively) {
12905
- if (!this.included) {
12906
- const jsx = this.scope.context.options.jsx;
12907
- if (jsx.mode === 'automatic') {
12908
- this.fragment = 'Fragment';
12909
- this.fragmentVariable = getAndIncludeFactoryVariable('Fragment', false, jsx.jsxImportSource, this);
12910
- }
12911
- else {
12912
- const { fragment, importSource, mode } = jsx;
12913
- if (fragment != null) {
12914
- this.fragment = fragment;
12915
- this.fragmentVariable = getAndIncludeFactoryVariable(fragment, mode === 'preserve', importSource, this);
12916
- }
13532
+ includeNode(context) {
13533
+ this.included = true;
13534
+ if (!this.deoptimized)
13535
+ this.applyDeoptimizations();
13536
+ const jsx = this.scope.context.options.jsx;
13537
+ if (jsx.mode === 'automatic') {
13538
+ this.fragment = 'Fragment';
13539
+ this.fragmentVariable = getAndIncludeFactoryVariable('Fragment', false, jsx.jsxImportSource, this, context);
13540
+ }
13541
+ else {
13542
+ const { fragment, importSource, mode } = jsx;
13543
+ if (fragment != null) {
13544
+ this.fragment = fragment;
13545
+ this.fragmentVariable = getAndIncludeFactoryVariable(fragment, mode === 'preserve', importSource, this, context);
12917
13546
  }
12918
13547
  }
12919
- super.include(context, includeChildrenRecursively);
12920
13548
  }
12921
13549
  render(code, options) {
12922
13550
  const { mode } = this.scope.context.options.jsx;
@@ -12953,6 +13581,7 @@ class JSXText extends NodeBase {
12953
13581
  }
12954
13582
  }
12955
13583
  }
13584
+ JSXText.prototype.includeNode = onlyIncludeSelf;
12956
13585
 
12957
13586
  class LabeledStatement extends NodeBase {
12958
13587
  hasEffects(context) {
@@ -12974,17 +13603,22 @@ class LabeledStatement extends NodeBase {
12974
13603
  return bodyHasEffects;
12975
13604
  }
12976
13605
  include(context, includeChildrenRecursively) {
12977
- this.included = true;
13606
+ if (!this.included)
13607
+ this.includeNode(context);
12978
13608
  const { brokenFlow, includedLabels } = context;
12979
13609
  context.includedLabels = new Set();
12980
13610
  this.body.include(context, includeChildrenRecursively);
12981
13611
  if (includeChildrenRecursively || context.includedLabels.has(this.label.name)) {
12982
- this.label.include();
13612
+ this.label.include(context);
12983
13613
  context.includedLabels.delete(this.label.name);
12984
13614
  context.brokenFlow = brokenFlow;
12985
13615
  }
12986
13616
  context.includedLabels = new Set([...includedLabels, ...context.includedLabels]);
12987
13617
  }
13618
+ includeNode(context) {
13619
+ this.included = true;
13620
+ this.body.includePath(UNKNOWN_PATH, context);
13621
+ }
12988
13622
  render(code, options) {
12989
13623
  if (this.label.included) {
12990
13624
  this.label.render(code, options);
@@ -12995,6 +13629,7 @@ class LabeledStatement extends NodeBase {
12995
13629
  this.body.render(code, options);
12996
13630
  }
12997
13631
  }
13632
+ LabeledStatement.prototype.applyDeoptimizations = doNotDeoptimize;
12998
13633
 
12999
13634
  class LogicalExpression extends NodeBase {
13000
13635
  constructor() {
@@ -13019,6 +13654,10 @@ class LogicalExpression extends NodeBase {
13019
13654
  const unusedBranch = this.usedBranch === this.left ? this.right : this.left;
13020
13655
  this.usedBranch = null;
13021
13656
  unusedBranch.deoptimizePath(UNKNOWN_PATH);
13657
+ if (this.included) {
13658
+ // As we are not tracking inclusions, we just include everything
13659
+ unusedBranch.includePath(UNKNOWN_PATH, createInclusionContext());
13660
+ }
13022
13661
  const { scope: { context }, expressionsToBeDeoptimized } = this;
13023
13662
  this.expressionsToBeDeoptimized = EMPTY_ARRAY;
13024
13663
  for (const expression of expressionsToBeDeoptimized) {
@@ -13041,23 +13680,25 @@ class LogicalExpression extends NodeBase {
13041
13680
  }
13042
13681
  getLiteralValueAtPath(path, recursionTracker, origin) {
13043
13682
  const usedBranch = this.getUsedBranch();
13044
- if (!usedBranch)
13045
- return UnknownValue;
13046
- this.expressionsToBeDeoptimized.push(origin);
13047
- return usedBranch.getLiteralValueAtPath(path, recursionTracker, origin);
13683
+ if (usedBranch) {
13684
+ this.expressionsToBeDeoptimized.push(origin);
13685
+ return usedBranch.getLiteralValueAtPath(path, recursionTracker, origin);
13686
+ }
13687
+ return UnknownValue;
13048
13688
  }
13049
13689
  getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin) {
13050
13690
  const usedBranch = this.getUsedBranch();
13051
- if (!usedBranch)
13052
- return [
13053
- new MultiExpression([
13054
- this.left.getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin)[0],
13055
- this.right.getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin)[0]
13056
- ]),
13057
- false
13058
- ];
13059
- this.expressionsToBeDeoptimized.push(origin);
13060
- return usedBranch.getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin);
13691
+ if (usedBranch) {
13692
+ this.expressionsToBeDeoptimized.push(origin);
13693
+ return usedBranch.getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin);
13694
+ }
13695
+ return [
13696
+ new MultiExpression([
13697
+ this.left.getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin)[0],
13698
+ this.right.getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin)[0]
13699
+ ]),
13700
+ false
13701
+ ];
13061
13702
  }
13062
13703
  hasEffects(context) {
13063
13704
  if (this.left.hasEffects(context)) {
@@ -13070,18 +13711,18 @@ class LogicalExpression extends NodeBase {
13070
13711
  }
13071
13712
  hasEffectsOnInteractionAtPath(path, interaction, context) {
13072
13713
  const usedBranch = this.getUsedBranch();
13073
- if (!usedBranch) {
13074
- return (this.left.hasEffectsOnInteractionAtPath(path, interaction, context) ||
13075
- this.right.hasEffectsOnInteractionAtPath(path, interaction, context));
13714
+ if (usedBranch) {
13715
+ return usedBranch.hasEffectsOnInteractionAtPath(path, interaction, context);
13076
13716
  }
13077
- return usedBranch.hasEffectsOnInteractionAtPath(path, interaction, context);
13717
+ return (this.left.hasEffectsOnInteractionAtPath(path, interaction, context) ||
13718
+ this.right.hasEffectsOnInteractionAtPath(path, interaction, context));
13078
13719
  }
13079
13720
  include(context, includeChildrenRecursively) {
13080
13721
  this.included = true;
13081
13722
  const usedBranch = this.getUsedBranch();
13082
13723
  if (includeChildrenRecursively ||
13083
- (usedBranch === this.right && this.left.shouldBeIncluded(context)) ||
13084
- !usedBranch) {
13724
+ !usedBranch ||
13725
+ (usedBranch === this.right && this.left.shouldBeIncluded(context))) {
13085
13726
  this.left.include(context, includeChildrenRecursively);
13086
13727
  this.right.include(context, includeChildrenRecursively);
13087
13728
  }
@@ -13089,6 +13730,17 @@ class LogicalExpression extends NodeBase {
13089
13730
  usedBranch.include(context, includeChildrenRecursively);
13090
13731
  }
13091
13732
  }
13733
+ includePath(path, context) {
13734
+ this.included = true;
13735
+ const usedBranch = this.getUsedBranch();
13736
+ if (!usedBranch || (usedBranch === this.right && this.left.shouldBeIncluded(context))) {
13737
+ this.left.includePath(path, context);
13738
+ this.right.includePath(path, context);
13739
+ }
13740
+ else {
13741
+ usedBranch.includePath(path, context);
13742
+ }
13743
+ }
13092
13744
  removeAnnotations(code) {
13093
13745
  this.left.removeAnnotations(code);
13094
13746
  }
@@ -13140,6 +13792,8 @@ class LogicalExpression extends NodeBase {
13140
13792
  return this.usedBranch;
13141
13793
  }
13142
13794
  }
13795
+ LogicalExpression.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
13796
+ LogicalExpression.prototype.applyDeoptimizations = doNotDeoptimize;
13143
13797
 
13144
13798
  class NewExpression extends NodeBase {
13145
13799
  hasEffects(context) {
@@ -13159,16 +13813,21 @@ class NewExpression extends NodeBase {
13159
13813
  return path.length > 0 || type !== INTERACTION_ACCESSED;
13160
13814
  }
13161
13815
  include(context, includeChildrenRecursively) {
13162
- if (!this.deoptimized)
13163
- this.applyDeoptimizations();
13164
13816
  if (includeChildrenRecursively) {
13165
13817
  super.include(context, includeChildrenRecursively);
13166
13818
  }
13167
13819
  else {
13168
- this.included = true;
13820
+ if (!this.included)
13821
+ this.includeNode(context);
13169
13822
  this.callee.include(context, false);
13170
13823
  }
13171
- this.callee.includeCallArguments(context, this.arguments);
13824
+ this.callee.includeCallArguments(context, this.interaction);
13825
+ }
13826
+ includeNode(context) {
13827
+ this.included = true;
13828
+ if (!this.deoptimized)
13829
+ this.applyDeoptimizations();
13830
+ this.callee.includePath(UNKNOWN_PATH, context);
13172
13831
  }
13173
13832
  initialise() {
13174
13833
  super.initialise();
@@ -13197,6 +13856,7 @@ class ObjectExpression extends NodeBase {
13197
13856
  constructor() {
13198
13857
  super(...arguments);
13199
13858
  this.objectEntity = null;
13859
+ this.protoProp = null;
13200
13860
  }
13201
13861
  deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
13202
13862
  this.getObjectEntity().deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker);
@@ -13216,15 +13876,43 @@ class ObjectExpression extends NodeBase {
13216
13876
  hasEffectsOnInteractionAtPath(path, interaction, context) {
13217
13877
  return this.getObjectEntity().hasEffectsOnInteractionAtPath(path, interaction, context);
13218
13878
  }
13879
+ include(context, includeChildrenRecursively) {
13880
+ if (!this.included)
13881
+ this.includeNode(context);
13882
+ this.getObjectEntity().include(context, includeChildrenRecursively);
13883
+ this.protoProp?.include(context, includeChildrenRecursively);
13884
+ }
13885
+ includeNode(context) {
13886
+ this.included = true;
13887
+ this.protoProp?.includePath(UNKNOWN_PATH, context);
13888
+ }
13889
+ includePath(path, context) {
13890
+ if (!this.included)
13891
+ this.includeNode(context);
13892
+ this.getObjectEntity().includePath(path, context);
13893
+ }
13219
13894
  render(code, options, { renderedSurroundingElement } = BLANK) {
13220
- super.render(code, options);
13221
13895
  if (renderedSurroundingElement === ExpressionStatement$1 ||
13222
13896
  renderedSurroundingElement === ArrowFunctionExpression$1) {
13223
13897
  code.appendRight(this.start, '(');
13224
13898
  code.prependLeft(this.end, ')');
13225
13899
  }
13900
+ if (this.properties.length > 0) {
13901
+ const separatedNodes = getCommaSeparatedNodesWithBoundaries(this.properties, code, this.start + 1, this.end - 1);
13902
+ let lastSeparatorPos = null;
13903
+ for (const { node, separator, start, end } of separatedNodes) {
13904
+ if (!node.included) {
13905
+ treeshakeNode(node, code, start, end);
13906
+ continue;
13907
+ }
13908
+ lastSeparatorPos = separator;
13909
+ node.render(code, options);
13910
+ }
13911
+ if (lastSeparatorPos) {
13912
+ code.remove(lastSeparatorPos, this.end - 1);
13913
+ }
13914
+ }
13226
13915
  }
13227
- applyDeoptimizations() { }
13228
13916
  getObjectEntity() {
13229
13917
  if (this.objectEntity !== null) {
13230
13918
  return this.objectEntity;
@@ -13253,6 +13941,7 @@ class ObjectExpression extends NodeBase {
13253
13941
  ? property.key.name
13254
13942
  : String(property.key.value);
13255
13943
  if (key === '__proto__' && property.kind === 'init') {
13944
+ this.protoProp = property;
13256
13945
  prototype =
13257
13946
  property.value instanceof Literal && property.value.value === null
13258
13947
  ? null
@@ -13265,6 +13954,7 @@ class ObjectExpression extends NodeBase {
13265
13954
  return (this.objectEntity = new ObjectEntity(properties, prototype));
13266
13955
  }
13267
13956
  }
13957
+ ObjectExpression.prototype.applyDeoptimizations = doNotDeoptimize;
13268
13958
 
13269
13959
  class PanicError extends NodeBase {
13270
13960
  initialise() {
@@ -13291,6 +13981,7 @@ class ParseError extends NodeBase {
13291
13981
 
13292
13982
  class PrivateIdentifier extends NodeBase {
13293
13983
  }
13984
+ PrivateIdentifier.prototype.includeNode = onlyIncludeSelf;
13294
13985
 
13295
13986
  class Program extends NodeBase {
13296
13987
  constructor() {
@@ -13358,14 +14049,11 @@ class Program extends NodeBase {
13358
14049
  super.render(code, options);
13359
14050
  }
13360
14051
  }
13361
- applyDeoptimizations() { }
13362
14052
  }
14053
+ Program.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
14054
+ Program.prototype.applyDeoptimizations = doNotDeoptimize;
13363
14055
 
13364
14056
  class Property extends MethodBase {
13365
- constructor() {
13366
- super(...arguments);
13367
- this.declarationInit = null;
13368
- }
13369
14057
  //declare method: boolean;
13370
14058
  get method() {
13371
14059
  return isFlagSet(this.flags, 262144 /* Flag.method */);
@@ -13380,17 +14068,41 @@ class Property extends MethodBase {
13380
14068
  set shorthand(value) {
13381
14069
  this.flags = setFlag(this.flags, 524288 /* Flag.shorthand */, value);
13382
14070
  }
13383
- declare(kind, init) {
13384
- this.declarationInit = init;
13385
- return this.value.declare(kind, UNKNOWN_EXPRESSION);
14071
+ declare(kind, destructuredInitPath, init) {
14072
+ return this.value.declare(kind, this.getPathInProperty(destructuredInitPath), init);
14073
+ }
14074
+ deoptimizeAssignment(destructuredInitPath, init) {
14075
+ this.value.deoptimizeAssignment?.(this.getPathInProperty(destructuredInitPath), init);
13386
14076
  }
13387
14077
  hasEffects(context) {
13388
- if (!this.deoptimized)
13389
- this.applyDeoptimizations();
13390
- const propertyReadSideEffects = this.scope.context.options.treeshake.propertyReadSideEffects;
13391
- return ((this.parent.type === 'ObjectPattern' && propertyReadSideEffects === 'always') ||
13392
- this.key.hasEffects(context) ||
13393
- this.value.hasEffects(context));
14078
+ return this.key.hasEffects(context) || this.value.hasEffects(context);
14079
+ }
14080
+ hasEffectsWhenDestructuring(context, destructuredInitPath, init) {
14081
+ return this.value.hasEffectsWhenDestructuring?.(context, this.getPathInProperty(destructuredInitPath), init);
14082
+ }
14083
+ includeDestructuredIfNecessary(context, destructuredInitPath, init) {
14084
+ const path = this.getPathInProperty(destructuredInitPath);
14085
+ let included = this.value.includeDestructuredIfNecessary(context, path, init) ||
14086
+ this.included;
14087
+ if ((included ||= this.key.hasEffects(createHasEffectsContext()))) {
14088
+ this.key.include(context, false);
14089
+ if (!this.value.included) {
14090
+ this.value.included = true;
14091
+ // Unfortunately, we need to include the value again now, so that any
14092
+ // declared variables are properly included.
14093
+ this.value.includeDestructuredIfNecessary(context, path, init);
14094
+ }
14095
+ }
14096
+ return (this.included = included);
14097
+ }
14098
+ include(context, includeChildrenRecursively) {
14099
+ this.included = true;
14100
+ this.key.include(context, includeChildrenRecursively);
14101
+ this.value.include(context, includeChildrenRecursively);
14102
+ }
14103
+ includePath(path, context) {
14104
+ this.included = true;
14105
+ this.value.includePath(path, context);
13394
14106
  }
13395
14107
  markDeclarationReached() {
13396
14108
  this.value.markDeclarationReached();
@@ -13401,14 +14113,20 @@ class Property extends MethodBase {
13401
14113
  }
13402
14114
  this.value.render(code, options, { isShorthandProperty: this.shorthand });
13403
14115
  }
13404
- applyDeoptimizations() {
13405
- this.deoptimized = true;
13406
- if (this.declarationInit !== null) {
13407
- this.declarationInit.deoptimizePath([UnknownKey, UnknownKey]);
13408
- this.scope.context.requestTreeshakingPass();
13409
- }
14116
+ getPathInProperty(destructuredInitPath) {
14117
+ return destructuredInitPath.at(-1) === UnknownKey
14118
+ ? destructuredInitPath
14119
+ : // For now, we only consider static paths as we do not know how to
14120
+ // deoptimize the path in the dynamic case.
14121
+ this.computed
14122
+ ? [...destructuredInitPath, UnknownKey]
14123
+ : this.key instanceof Identifier
14124
+ ? [...destructuredInitPath, this.key.name]
14125
+ : [...destructuredInitPath, String(this.key.value)];
13410
14126
  }
13411
14127
  }
14128
+ Property.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
14129
+ Property.prototype.applyDeoptimizations = doNotDeoptimize;
13412
14130
 
13413
14131
  class PropertyDefinition extends NodeBase {
13414
14132
  get computed() {
@@ -13441,8 +14159,15 @@ class PropertyDefinition extends NodeBase {
13441
14159
  hasEffectsOnInteractionAtPath(path, interaction, context) {
13442
14160
  return !this.value || this.value.hasEffectsOnInteractionAtPath(path, interaction, context);
13443
14161
  }
13444
- applyDeoptimizations() { }
14162
+ includeNode(context) {
14163
+ this.included = true;
14164
+ this.value?.includePath(UNKNOWN_PATH, context);
14165
+ for (const decorator of this.decorators) {
14166
+ decorator.includePath(UNKNOWN_PATH, context);
14167
+ }
14168
+ }
13445
14169
  }
14170
+ PropertyDefinition.prototype.applyDeoptimizations = doNotDeoptimize;
13446
14171
 
13447
14172
  class ReturnStatement extends NodeBase {
13448
14173
  hasEffects(context) {
@@ -13452,10 +14177,15 @@ class ReturnStatement extends NodeBase {
13452
14177
  return false;
13453
14178
  }
13454
14179
  include(context, includeChildrenRecursively) {
13455
- this.included = true;
14180
+ if (!this.included)
14181
+ this.includeNode(context);
13456
14182
  this.argument?.include(context, includeChildrenRecursively);
13457
14183
  context.brokenFlow = true;
13458
14184
  }
14185
+ includeNode(context) {
14186
+ this.included = true;
14187
+ this.argument?.includePath(UNKNOWN_PATH, context);
14188
+ }
13459
14189
  initialise() {
13460
14190
  super.initialise();
13461
14191
  this.scope.addReturnExpression(this.argument || UNKNOWN_EXPRESSION);
@@ -13469,6 +14199,7 @@ class ReturnStatement extends NodeBase {
13469
14199
  }
13470
14200
  }
13471
14201
  }
14202
+ ReturnStatement.prototype.applyDeoptimizations = doNotDeoptimize;
13472
14203
 
13473
14204
  class SequenceExpression extends NodeBase {
13474
14205
  deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
@@ -13496,10 +14227,15 @@ class SequenceExpression extends NodeBase {
13496
14227
  for (const expression of this.expressions) {
13497
14228
  if (includeChildrenRecursively ||
13498
14229
  (expression === lastExpression && !(this.parent instanceof ExpressionStatement)) ||
13499
- expression.shouldBeIncluded(context))
14230
+ expression.shouldBeIncluded(context)) {
13500
14231
  expression.include(context, includeChildrenRecursively);
14232
+ }
13501
14233
  }
13502
14234
  }
14235
+ includePath(path, context) {
14236
+ this.included = true;
14237
+ this.expressions[this.expressions.length - 1].includePath(path, context);
14238
+ }
13503
14239
  removeAnnotations(code) {
13504
14240
  this.expressions[0].removeAnnotations(code);
13505
14241
  }
@@ -13534,6 +14270,8 @@ class SequenceExpression extends NodeBase {
13534
14270
  }
13535
14271
  }
13536
14272
  }
14273
+ SequenceExpression.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
14274
+ SequenceExpression.prototype.applyDeoptimizations = doNotDeoptimize;
13537
14275
 
13538
14276
  class Super extends NodeBase {
13539
14277
  bind() {
@@ -13545,11 +14283,15 @@ class Super extends NodeBase {
13545
14283
  deoptimizePath(path) {
13546
14284
  this.variable.deoptimizePath(path);
13547
14285
  }
13548
- include() {
13549
- if (!this.included) {
13550
- this.included = true;
13551
- this.scope.context.includeVariableInModule(this.variable);
13552
- }
14286
+ include(context) {
14287
+ if (!this.included)
14288
+ this.includeNode(context);
14289
+ }
14290
+ includeNode(context) {
14291
+ this.included = true;
14292
+ if (!this.deoptimized)
14293
+ this.applyDeoptimizations();
14294
+ this.scope.context.includeVariableInModule(this.variable, EMPTY_PATH, context);
13553
14295
  }
13554
14296
  }
13555
14297
 
@@ -13590,6 +14332,8 @@ class SwitchCase extends NodeBase {
13590
14332
  }
13591
14333
  }
13592
14334
  SwitchCase.prototype.needsBoundaries = true;
14335
+ SwitchCase.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
14336
+ SwitchCase.prototype.applyDeoptimizations = doNotDeoptimize;
13593
14337
 
13594
14338
  class SwitchStatement extends NodeBase {
13595
14339
  createScope(parentScope) {
@@ -13672,6 +14416,8 @@ class SwitchStatement extends NodeBase {
13672
14416
  }
13673
14417
  }
13674
14418
  }
14419
+ SwitchStatement.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
14420
+ SwitchStatement.prototype.applyDeoptimizations = doNotDeoptimize;
13675
14421
 
13676
14422
  class TaggedTemplateExpression extends CallExpressionBase {
13677
14423
  bind() {
@@ -13695,8 +14441,8 @@ class TaggedTemplateExpression extends CallExpressionBase {
13695
14441
  this.tag.hasEffectsOnInteractionAtPath(EMPTY_PATH, this.interaction, context));
13696
14442
  }
13697
14443
  include(context, includeChildrenRecursively) {
13698
- if (!this.deoptimized)
13699
- this.applyDeoptimizations();
14444
+ if (!this.included)
14445
+ this.includeNode(context);
13700
14446
  if (includeChildrenRecursively) {
13701
14447
  super.include(context, includeChildrenRecursively);
13702
14448
  }
@@ -13705,7 +14451,7 @@ class TaggedTemplateExpression extends CallExpressionBase {
13705
14451
  this.tag.include(context, includeChildrenRecursively);
13706
14452
  this.quasi.include(context, includeChildrenRecursively);
13707
14453
  }
13708
- this.tag.includeCallArguments(context, this.args);
14454
+ this.tag.includeCallArguments(context, this.interaction);
13709
14455
  const [returnExpression] = this.getReturnExpression();
13710
14456
  if (!returnExpression.included) {
13711
14457
  returnExpression.include(context, false);
@@ -13740,6 +14486,7 @@ class TaggedTemplateExpression extends CallExpressionBase {
13740
14486
  return this.returnExpression;
13741
14487
  }
13742
14488
  }
14489
+ TaggedTemplateExpression.prototype.includeNode = onlyIncludeSelf;
13743
14490
 
13744
14491
  class TemplateElement extends NodeBase {
13745
14492
  get tail() {
@@ -13753,15 +14500,13 @@ class TemplateElement extends NodeBase {
13753
14500
  hasEffects() {
13754
14501
  return false;
13755
14502
  }
13756
- include() {
13757
- this.included = true;
13758
- }
13759
14503
  parseNode(esTreeNode) {
13760
14504
  this.value = esTreeNode.value;
13761
14505
  return super.parseNode(esTreeNode);
13762
14506
  }
13763
14507
  render() { }
13764
14508
  }
14509
+ TemplateElement.prototype.includeNode = onlyIncludeSelf;
13765
14510
 
13766
14511
  class TemplateLiteral extends NodeBase {
13767
14512
  deoptimizeArgumentsOnInteractionAtPath() { }
@@ -13786,6 +14531,14 @@ class TemplateLiteral extends NodeBase {
13786
14531
  }
13787
14532
  return true;
13788
14533
  }
14534
+ includeNode(context) {
14535
+ this.included = true;
14536
+ if (!this.deoptimized)
14537
+ this.applyDeoptimizations();
14538
+ for (const node of this.expressions) {
14539
+ node.includePath(UNKNOWN_PATH, context);
14540
+ }
14541
+ }
13789
14542
  render(code, options) {
13790
14543
  code.indentExclusionRanges.push([this.start, this.end]);
13791
14544
  super.render(code, options);
@@ -13795,13 +14548,13 @@ class TemplateLiteral extends NodeBase {
13795
14548
  class ModuleScope extends ChildScope {
13796
14549
  constructor(parent, context) {
13797
14550
  super(parent, context);
13798
- this.variables.set('this', new LocalVariable('this', null, UNDEFINED_EXPRESSION, context, 'other'));
14551
+ this.variables.set('this', new LocalVariable('this', null, UNDEFINED_EXPRESSION, EMPTY_PATH, context, 'other'));
13799
14552
  }
13800
- addDeclaration(identifier, context, init, kind) {
14553
+ addDeclaration(identifier, context, init, destructuredInitPath, kind) {
13801
14554
  if (this.context.module.importDescriptions.has(identifier.name)) {
13802
14555
  context.error(logRedeclarationError(identifier.name), identifier.start);
13803
14556
  }
13804
- return super.addDeclaration(identifier, context, init, kind);
14557
+ return super.addDeclaration(identifier, context, init, destructuredInitPath, kind);
13805
14558
  }
13806
14559
  addExportDefaultDeclaration(name, exportDefaultDeclaration, context) {
13807
14560
  const variable = new ExportDefaultVariable(name, exportDefaultDeclaration, context);
@@ -13846,10 +14599,23 @@ class ThisExpression extends NodeBase {
13846
14599
  }
13847
14600
  return this.variable.hasEffectsOnInteractionAtPath(path, interaction, context);
13848
14601
  }
13849
- include() {
14602
+ include(context) {
14603
+ if (!this.included)
14604
+ this.includeNode(context);
14605
+ }
14606
+ includeNode(context) {
14607
+ this.included = true;
14608
+ if (!this.deoptimized)
14609
+ this.applyDeoptimizations();
14610
+ this.scope.context.includeVariableInModule(this.variable, EMPTY_PATH, context);
14611
+ }
14612
+ includePath(path, context) {
13850
14613
  if (!this.included) {
13851
14614
  this.included = true;
13852
- this.scope.context.includeVariableInModule(this.variable);
14615
+ this.scope.context.includeVariableInModule(this.variable, path, context);
14616
+ }
14617
+ else if (path.length > 0) {
14618
+ this.variable.includePath(path, context);
13853
14619
  }
13854
14620
  }
13855
14621
  initialise() {
@@ -13877,7 +14643,8 @@ class ThrowStatement extends NodeBase {
13877
14643
  return true;
13878
14644
  }
13879
14645
  include(context, includeChildrenRecursively) {
13880
- this.included = true;
14646
+ if (!this.included)
14647
+ this.includeNode(context);
13881
14648
  this.argument.include(context, includeChildrenRecursively);
13882
14649
  context.brokenFlow = true;
13883
14650
  }
@@ -13888,6 +14655,7 @@ class ThrowStatement extends NodeBase {
13888
14655
  }
13889
14656
  }
13890
14657
  }
14658
+ ThrowStatement.prototype.includeNode = onlyIncludeSelf;
13891
14659
 
13892
14660
  class TryStatement extends NodeBase {
13893
14661
  constructor() {
@@ -13924,6 +14692,8 @@ class TryStatement extends NodeBase {
13924
14692
  this.finalizer?.include(context, includeChildrenRecursively);
13925
14693
  }
13926
14694
  }
14695
+ TryStatement.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
14696
+ TryStatement.prototype.applyDeoptimizations = doNotDeoptimize;
13927
14697
 
13928
14698
  const unaryOperators = {
13929
14699
  '!': value => !value,
@@ -13969,6 +14739,7 @@ class UnaryExpression extends NodeBase {
13969
14739
  }
13970
14740
  }
13971
14741
  }
14742
+ UnaryExpression.prototype.includeNode = onlyIncludeSelf;
13972
14743
 
13973
14744
  class UpdateExpression extends NodeBase {
13974
14745
  hasEffects(context) {
@@ -13980,9 +14751,8 @@ class UpdateExpression extends NodeBase {
13980
14751
  return path.length > 1 || type !== INTERACTION_ACCESSED;
13981
14752
  }
13982
14753
  include(context, includeChildrenRecursively) {
13983
- if (!this.deoptimized)
13984
- this.applyDeoptimizations();
13985
- this.included = true;
14754
+ if (!this.included)
14755
+ this.includeNode(context);
13986
14756
  this.argument.includeAsAssignmentTarget(context, includeChildrenRecursively, true);
13987
14757
  }
13988
14758
  initialise() {
@@ -14021,6 +14791,7 @@ class UpdateExpression extends NodeBase {
14021
14791
  this.scope.context.requestTreeshakingPass();
14022
14792
  }
14023
14793
  }
14794
+ UpdateExpression.prototype.includeNode = onlyIncludeSelf;
14024
14795
 
14025
14796
  function areAllDeclarationsIncludedAndNotExported(declarations, exportNamesByVariable) {
14026
14797
  for (const declarator of declarations) {
@@ -14051,8 +14822,9 @@ class VariableDeclaration extends NodeBase {
14051
14822
  include(context, includeChildrenRecursively, { asSingleStatement } = BLANK) {
14052
14823
  this.included = true;
14053
14824
  for (const declarator of this.declarations) {
14054
- if (includeChildrenRecursively || declarator.shouldBeIncluded(context))
14825
+ if (includeChildrenRecursively || declarator.shouldBeIncluded(context)) {
14055
14826
  declarator.include(context, includeChildrenRecursively);
14827
+ }
14056
14828
  const { id, init } = declarator;
14057
14829
  if (asSingleStatement) {
14058
14830
  id.include(context, includeChildrenRecursively);
@@ -14090,7 +14862,6 @@ class VariableDeclaration extends NodeBase {
14090
14862
  this.renderReplacedDeclarations(code, options);
14091
14863
  }
14092
14864
  }
14093
- applyDeoptimizations() { }
14094
14865
  renderDeclarationEnd(code, separatorString, lastSeparatorPos, actualContentEnd, renderedContentEnd, systemPatternExports, options) {
14095
14866
  if (code.original.charCodeAt(this.end - 1) === 59 /*";"*/) {
14096
14867
  code.remove(this.end - 1, this.end);
@@ -14133,8 +14904,7 @@ class VariableDeclaration extends NodeBase {
14133
14904
  const singleSystemExport = gatherSystemExportsAndGetSingleExport(separatedNodes, options, aggregatedSystemExports);
14134
14905
  for (const { node, start, separator, contentEnd, end } of separatedNodes) {
14135
14906
  if (!node.included) {
14136
- code.remove(start, end);
14137
- node.removeAnnotations(code);
14907
+ treeshakeNode(node, code, start, end);
14138
14908
  continue;
14139
14909
  }
14140
14910
  node.render(code, options);
@@ -14204,6 +14974,8 @@ function gatherSystemExportsAndGetSingleExport(separatedNodes, options, aggregat
14204
14974
  }
14205
14975
  return singleSystemExport;
14206
14976
  }
14977
+ VariableDeclaration.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
14978
+ VariableDeclaration.prototype.applyDeoptimizations = doNotDeoptimize;
14207
14979
 
14208
14980
  class WhileStatement extends NodeBase {
14209
14981
  hasEffects(context) {
@@ -14217,13 +14989,25 @@ class WhileStatement extends NodeBase {
14217
14989
  includeLoopBody(context, this.body, includeChildrenRecursively);
14218
14990
  }
14219
14991
  }
14992
+ WhileStatement.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
14993
+ WhileStatement.prototype.applyDeoptimizations = doNotDeoptimize;
14220
14994
 
14221
14995
  class YieldExpression extends NodeBase {
14996
+ applyDeoptimizations() {
14997
+ this.deoptimized = true;
14998
+ this.argument?.deoptimizePath(UNKNOWN_PATH);
14999
+ }
14222
15000
  hasEffects(context) {
14223
15001
  if (!this.deoptimized)
14224
15002
  this.applyDeoptimizations();
14225
15003
  return !(context.ignore.returnYield && !this.argument?.hasEffects(context));
14226
15004
  }
15005
+ includeNode(context) {
15006
+ this.included = true;
15007
+ if (!this.deoptimized)
15008
+ this.applyDeoptimizations();
15009
+ this.argument?.includePath(UNKNOWN_PATH, context);
15010
+ }
14227
15011
  render(code, options) {
14228
15012
  if (this.argument) {
14229
15013
  this.argument.render(code, options, { preventASI: true });
@@ -14457,7 +15241,7 @@ const bufferParsers = [
14457
15241
  const annotations = (node.annotations = convertAnnotations(buffer[position + 1], buffer));
14458
15242
  node.annotationNoSideEffects = annotations.some(comment => comment.type === 'noSideEffects');
14459
15243
  const parameters = (node.params = convertNodeList(node, scope, buffer[position + 2], buffer));
14460
- scope.addParameterVariables(parameters.map(parameter => parameter.declare('parameter', UNKNOWN_EXPRESSION)), parameters[parameters.length - 1] instanceof RestElement);
15244
+ scope.addParameterVariables(parameters.map(parameter => parameter.declare('parameter', EMPTY_PATH, UNKNOWN_EXPRESSION)), parameters[parameters.length - 1] instanceof RestElement);
14461
15245
  node.body = convertNode(node, scope.bodyScope, buffer[position + 3], buffer);
14462
15246
  },
14463
15247
  function assignmentExpression(node, position, buffer) {
@@ -14503,7 +15287,7 @@ const bufferParsers = [
14503
15287
  const parameterPosition = buffer[position];
14504
15288
  const parameter = (node.param =
14505
15289
  parameterPosition === 0 ? null : convertNode(node, scope, parameterPosition, buffer));
14506
- parameter?.declare('parameter', UNKNOWN_EXPRESSION);
15290
+ parameter?.declare('parameter', EMPTY_PATH, UNKNOWN_EXPRESSION);
14507
15291
  node.body = convertNode(node, scope.bodyScope, buffer[position + 1], buffer);
14508
15292
  },
14509
15293
  function chainExpression(node, position, buffer) {
@@ -14641,7 +15425,7 @@ const bufferParsers = [
14641
15425
  node.id =
14642
15426
  idPosition === 0 ? null : convertNode(node, scope.parent, idPosition, buffer);
14643
15427
  const parameters = (node.params = convertNodeList(node, scope, buffer[position + 3], buffer));
14644
- scope.addParameterVariables(parameters.map(parameter => parameter.declare('parameter', UNKNOWN_EXPRESSION)), parameters[parameters.length - 1] instanceof RestElement);
15428
+ scope.addParameterVariables(parameters.map(parameter => parameter.declare('parameter', EMPTY_PATH, UNKNOWN_EXPRESSION)), parameters[parameters.length - 1] instanceof RestElement);
14645
15429
  node.body = convertNode(node, scope.bodyScope, buffer[position + 4], buffer);
14646
15430
  },
14647
15431
  function functionExpression(node, position, buffer) {
@@ -14654,7 +15438,7 @@ const bufferParsers = [
14654
15438
  const idPosition = buffer[position + 2];
14655
15439
  node.id = idPosition === 0 ? null : convertNode(node, node.idScope, idPosition, buffer);
14656
15440
  const parameters = (node.params = convertNodeList(node, scope, buffer[position + 3], buffer));
14657
- scope.addParameterVariables(parameters.map(parameter => parameter.declare('parameter', UNKNOWN_EXPRESSION)), parameters[parameters.length - 1] instanceof RestElement);
15441
+ scope.addParameterVariables(parameters.map(parameter => parameter.declare('parameter', EMPTY_PATH, UNKNOWN_EXPRESSION)), parameters[parameters.length - 1] instanceof RestElement);
14658
15442
  node.body = convertNode(node, scope.bodyScope, buffer[position + 4], buffer);
14659
15443
  },
14660
15444
  function identifier(node, position, buffer) {
@@ -15118,8 +15902,8 @@ class ExportShimVariable extends Variable {
15118
15902
  super(MISSING_EXPORT_SHIM_VARIABLE);
15119
15903
  this.module = module;
15120
15904
  }
15121
- include() {
15122
- super.include();
15905
+ includePath(path, context) {
15906
+ super.includePath(path, context);
15123
15907
  this.module.needsExportShim = true;
15124
15908
  }
15125
15909
  }
@@ -15817,16 +16601,15 @@ class Module {
15817
16601
  markModuleAndImpureDependenciesAsExecuted(this);
15818
16602
  this.graph.needsTreeshakingPass = true;
15819
16603
  }
16604
+ const inclusionContext = createInclusionContext();
15820
16605
  for (const exportName of this.exports.keys()) {
15821
16606
  if (includeNamespaceMembers || exportName !== this.info.syntheticNamedExports) {
15822
16607
  const variable = this.getVariableForExportName(exportName)[0];
15823
16608
  if (!variable) {
15824
16609
  return error(logMissingEntryExport(exportName, this.id));
15825
16610
  }
16611
+ this.includeVariable(variable, UNKNOWN_PATH, inclusionContext);
15826
16612
  variable.deoptimizePath(UNKNOWN_PATH);
15827
- if (!variable.included) {
15828
- this.includeVariable(variable);
15829
- }
15830
16613
  }
15831
16614
  }
15832
16615
  for (const name of this.getReexports()) {
@@ -15834,7 +16617,7 @@ class Module {
15834
16617
  if (variable) {
15835
16618
  variable.deoptimizePath(UNKNOWN_PATH);
15836
16619
  if (!variable.included) {
15837
- this.includeVariable(variable);
16620
+ this.includeVariable(variable, UNKNOWN_PATH, inclusionContext);
15838
16621
  }
15839
16622
  if (variable instanceof ExternalVariable) {
15840
16623
  variable.module.reexported = true;
@@ -15855,13 +16638,12 @@ class Module {
15855
16638
  this.graph.needsTreeshakingPass = true;
15856
16639
  }
15857
16640
  let includeNamespaceMembers = false;
16641
+ const inclusionContext = createInclusionContext();
15858
16642
  for (const name of names) {
15859
16643
  const variable = this.getVariableForExportName(name)[0];
15860
16644
  if (variable) {
15861
16645
  variable.deoptimizePath(UNKNOWN_PATH);
15862
- if (!variable.included) {
15863
- this.includeVariable(variable);
15864
- }
16646
+ this.includeVariable(variable, UNKNOWN_PATH, inclusionContext);
15865
16647
  }
15866
16648
  if (!this.exports.has(name) && !this.reexportDescriptions.has(name)) {
15867
16649
  includeNamespaceMembers = true;
@@ -15962,6 +16744,7 @@ class Module {
15962
16744
  manualPureFunctions: this.graph.pureFunctions,
15963
16745
  module: this,
15964
16746
  moduleContext: this.context,
16747
+ newlyIncludedVariableInits: this.graph.newlyIncludedVariableInits,
15965
16748
  options: this.options,
15966
16749
  requestTreeshakingPass: () => (this.graph.needsTreeshakingPass = true),
15967
16750
  traceExport: (name) => this.getVariableForExportName(name)[0],
@@ -16302,13 +17085,13 @@ class Module {
16302
17085
  for (const module of [this, ...this.exportAllModules]) {
16303
17086
  if (module instanceof ExternalModule) {
16304
17087
  const [externalVariable] = module.getVariableForExportName('*');
16305
- externalVariable.include();
17088
+ externalVariable.includePath(UNKNOWN_PATH, createInclusionContext());
16306
17089
  this.includedImports.add(externalVariable);
16307
17090
  externalNamespaces.add(externalVariable);
16308
17091
  }
16309
17092
  else if (module.info.syntheticNamedExports) {
16310
17093
  const syntheticNamespace = module.getSyntheticNamespace();
16311
- syntheticNamespace.include();
17094
+ syntheticNamespace.includePath(UNKNOWN_PATH, createInclusionContext());
16312
17095
  this.includedImports.add(syntheticNamespace);
16313
17096
  syntheticNamespaces.add(syntheticNamespace);
16314
17097
  }
@@ -16318,7 +17101,9 @@ class Module {
16318
17101
  includeDynamicImport(node) {
16319
17102
  const resolution = this.dynamicImports.find(dynamicImport => dynamicImport.node === node).resolution;
16320
17103
  if (resolution instanceof Module) {
16321
- resolution.includedDynamicImporters.push(this);
17104
+ if (!resolution.includedDynamicImporters.includes(this)) {
17105
+ resolution.includedDynamicImporters.push(this);
17106
+ }
16322
17107
  const importedNames = this.options.treeshake
16323
17108
  ? node.getDeterministicImportedNames()
16324
17109
  : undefined;
@@ -16330,15 +17115,15 @@ class Module {
16330
17115
  }
16331
17116
  }
16332
17117
  }
16333
- includeVariable(variable) {
16334
- const variableModule = variable.module;
16335
- if (variable.included) {
17118
+ includeVariable(variable, path, context) {
17119
+ const { included, module: variableModule } = variable;
17120
+ variable.includePath(path, context);
17121
+ if (included) {
16336
17122
  if (variableModule instanceof Module && variableModule !== this) {
16337
17123
  getAndExtendSideEffectModules(variable, this);
16338
17124
  }
16339
17125
  }
16340
17126
  else {
16341
- variable.include();
16342
17127
  this.graph.needsTreeshakingPass = true;
16343
17128
  if (variableModule instanceof Module) {
16344
17129
  if (!variableModule.isExecuted) {
@@ -16355,8 +17140,8 @@ class Module {
16355
17140
  }
16356
17141
  }
16357
17142
  }
16358
- includeVariableInModule(variable) {
16359
- this.includeVariable(variable);
17143
+ includeVariableInModule(variable, path, context) {
17144
+ this.includeVariable(variable, path, context);
16360
17145
  const variableModule = variable.module;
16361
17146
  if (variableModule && variableModule !== this) {
16362
17147
  this.includedImports.add(variable);
@@ -20953,10 +21738,11 @@ class Graph {
20953
21738
  this.options = options;
20954
21739
  this.astLru = flru(5);
20955
21740
  this.cachedModules = new Map();
20956
- this.deoptimizationTracker = new PathTracker();
21741
+ this.deoptimizationTracker = new EntityPathTracker();
20957
21742
  this.entryModules = [];
20958
21743
  this.modulesById = new Map();
20959
21744
  this.needsTreeshakingPass = false;
21745
+ this.newlyIncludedVariableInits = new Set();
20960
21746
  this.phase = BuildPhase.LOAD_AND_PARSE;
20961
21747
  this.scope = new GlobalScope();
20962
21748
  this.watchFiles = Object.create(null);
@@ -21050,6 +21836,7 @@ class Graph {
21050
21836
  }
21051
21837
  if (this.options.treeshake) {
21052
21838
  let treeshakingPass = 1;
21839
+ this.newlyIncludedVariableInits.clear();
21053
21840
  do {
21054
21841
  timeStart(`treeshaking pass ${treeshakingPass}`, 3);
21055
21842
  this.needsTreeshakingPass = false;
@@ -21074,6 +21861,10 @@ class Graph {
21074
21861
  }
21075
21862
  }
21076
21863
  }
21864
+ for (const entity of this.newlyIncludedVariableInits) {
21865
+ this.newlyIncludedVariableInits.delete(entity);
21866
+ entity.include(createInclusionContext(), false);
21867
+ }
21077
21868
  timeEnd(`treeshaking pass ${treeshakingPass++}`, 3);
21078
21869
  } while (this.needsTreeshakingPass);
21079
21870
  }
@@ -21953,7 +22744,7 @@ createColors();
21953
22744
 
21954
22745
  // @see https://no-color.org
21955
22746
  // @see https://www.npmjs.com/package/chalk
21956
- const { bold, cyan, dim, gray, green, red, underline, yellow } = createColors({
22747
+ const { bold, cyan, dim, red} = createColors({
21957
22748
  useColor: env$1.FORCE_COLOR !== '0' && !env$1.NO_COLOR
21958
22749
  });
21959
22750