@rollup/wasm-node 4.29.0 → 4.30.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.29.0
4
- Fri, 20 Dec 2024 18:36:54 GMT - commit dadd4882c4984d7875af799ad56e506784d50e1c
3
+ Rollup.js v4.30.0-0
4
+ Sat, 21 Dec 2024 07:16:43 GMT - commit 2339f1d8384a8999645823f83f9042a9fc7b3bf7
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.29.0";
19
+ var version = "4.30.0-0";
20
20
 
21
21
  const comma = ','.charCodeAt(0);
22
22
  const semicolon = ';'.charCodeAt(0);
@@ -1965,71 +1965,6 @@ function renderSystemExportSequenceBeforeExpression(exportedVariable, expression
1965
1965
  }
1966
1966
  }
1967
1967
 
1968
- /** @import { Node } from 'estree' */
1969
-
1970
- /**
1971
- * @param {Node} node
1972
- * @param {Node} parent
1973
- * @returns {boolean}
1974
- */
1975
- function is_reference(node, parent) {
1976
- if (node.type === 'MemberExpression') {
1977
- return !node.computed && is_reference(node.object, node);
1978
- }
1979
-
1980
- if (node.type !== 'Identifier') return false;
1981
-
1982
- switch (parent?.type) {
1983
- // disregard `bar` in `foo.bar`
1984
- case 'MemberExpression':
1985
- return parent.computed || node === parent.object;
1986
-
1987
- // disregard the `foo` in `class {foo(){}}` but keep it in `class {[foo](){}}`
1988
- case 'MethodDefinition':
1989
- return parent.computed;
1990
-
1991
- // disregard the `meta` in `import.meta`
1992
- case 'MetaProperty':
1993
- return parent.meta === node;
1994
-
1995
- // disregard the `foo` in `class {foo=bar}` but keep it in `class {[foo]=bar}` and `class {bar=foo}`
1996
- case 'PropertyDefinition':
1997
- return parent.computed || node === parent.value;
1998
-
1999
- // disregard the `bar` in `{ bar: foo }`, but keep it in `{ [bar]: foo }`
2000
- case 'Property':
2001
- return parent.computed || node === parent.value;
2002
-
2003
- // disregard the `bar` in `export { foo as bar }` or
2004
- // the foo in `import { foo as bar }`
2005
- case 'ExportSpecifier':
2006
- case 'ImportSpecifier':
2007
- return node === parent.local;
2008
-
2009
- // disregard the `foo` in `foo: while (...) { ... break foo; ... continue foo;}`
2010
- case 'LabeledStatement':
2011
- case 'BreakStatement':
2012
- case 'ContinueStatement':
2013
- return false;
2014
-
2015
- default:
2016
- return true;
2017
- }
2018
- }
2019
-
2020
- const PureFunctionKey = Symbol('PureFunction');
2021
- const getPureFunctions = ({ treeshake }) => {
2022
- const pureFunctions = Object.create(null);
2023
- for (const functionName of treeshake ? treeshake.manualPureFunctions : []) {
2024
- let currentFunctions = pureFunctions;
2025
- for (const pathSegment of functionName.split('.')) {
2026
- currentFunctions = currentFunctions[pathSegment] ||= Object.create(null);
2027
- }
2028
- currentFunctions[PureFunctionKey] = true;
2029
- }
2030
- return pureFunctions;
2031
- };
2032
-
2033
1968
  function getOrCreate(map, key, init) {
2034
1969
  const existing = map.get(key);
2035
1970
  if (existing !== undefined) {
@@ -2060,7 +1995,7 @@ const UNKNOWN_PATH = [UnknownKey];
2060
1995
  const UNKNOWN_NON_ACCESSOR_PATH = [UnknownNonAccessorKey];
2061
1996
  const UNKNOWN_INTEGER_PATH = [UnknownInteger];
2062
1997
  const EntitiesKey = Symbol('Entities');
2063
- class PathTracker {
1998
+ class EntityPathTracker {
2064
1999
  constructor() {
2065
2000
  this.entityPaths = Object.create(null, {
2066
2001
  [EntitiesKey]: { value: new Set() }
@@ -2085,14 +2020,14 @@ class PathTracker {
2085
2020
  getEntities(path) {
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 Set() } });
2023
+ currentPaths = currentPaths[pathSegment] ||= Object.create(null, {
2024
+ [EntitiesKey]: { value: new Set() }
2025
+ });
2091
2026
  }
2092
2027
  return currentPaths[EntitiesKey];
2093
2028
  }
2094
2029
  }
2095
- const SHARED_RECURSION_TRACKER = new PathTracker();
2030
+ const SHARED_RECURSION_TRACKER = new EntityPathTracker();
2096
2031
  class DiscriminatedPathTracker {
2097
2032
  constructor() {
2098
2033
  this.entityPaths = Object.create(null, {
@@ -2102,9 +2037,9 @@ class DiscriminatedPathTracker {
2102
2037
  trackEntityAtPathAndGetIfTracked(path, discriminator, entity) {
2103
2038
  let currentPaths = this.entityPaths;
2104
2039
  for (const pathSegment of path) {
2105
- currentPaths = currentPaths[pathSegment] =
2106
- currentPaths[pathSegment] ||
2107
- Object.create(null, { [EntitiesKey]: { value: new Map() } });
2040
+ currentPaths = currentPaths[pathSegment] ||= Object.create(null, {
2041
+ [EntitiesKey]: { value: new Map() }
2042
+ });
2108
2043
  }
2109
2044
  const trackedEntities = getOrCreate(currentPaths[EntitiesKey], discriminator, (getNewSet));
2110
2045
  if (trackedEntities.has(entity))
@@ -2113,6 +2048,137 @@ class DiscriminatedPathTracker {
2113
2048
  return false;
2114
2049
  }
2115
2050
  }
2051
+ const UNKNOWN_INCLUDED_PATH = Object.freeze({ [UnknownKey]: EMPTY_OBJECT });
2052
+ class IncludedPathTracker {
2053
+ constructor() {
2054
+ this.includedPaths = null;
2055
+ }
2056
+ includePathAndGetIfIncluded(path) {
2057
+ let included = true;
2058
+ let parent = this;
2059
+ let parentSegment = 'includedPaths';
2060
+ let currentPaths = (this.includedPaths ||=
2061
+ ((included = false), Object.create(null)));
2062
+ for (const pathSegment of path) {
2063
+ // This means from here, all paths are included
2064
+ if (currentPaths[UnknownKey]) {
2065
+ return true;
2066
+ }
2067
+ // Including UnknownKey automatically includes all nested paths.
2068
+ // From above, we know that UnknownKey is not included yet.
2069
+ if (typeof pathSegment === 'symbol') {
2070
+ // Hopefully, this saves some memory over just setting
2071
+ // currentPaths[UnknownKey] = EMPTY_OBJECT
2072
+ parent[parentSegment] = UNKNOWN_INCLUDED_PATH;
2073
+ return false;
2074
+ }
2075
+ parent = currentPaths;
2076
+ parentSegment = pathSegment;
2077
+ currentPaths = currentPaths[pathSegment] ||= ((included = false), Object.create(null));
2078
+ }
2079
+ return included;
2080
+ }
2081
+ includeAllPaths(entity, context, basePath) {
2082
+ const { includedPaths } = this;
2083
+ if (includedPaths) {
2084
+ includeAllPaths(entity, context, basePath, includedPaths);
2085
+ }
2086
+ }
2087
+ }
2088
+ function includeAllPaths(entity, context, basePath, currentPaths) {
2089
+ if (currentPaths[UnknownKey]) {
2090
+ return entity.includePath([...basePath, UnknownKey], context);
2091
+ }
2092
+ const keys = Object.keys(currentPaths);
2093
+ if (keys.length === 0) {
2094
+ return entity.includePath(basePath, context);
2095
+ }
2096
+ for (const key of keys) {
2097
+ includeAllPaths(entity, context, [...basePath, key], currentPaths[key]);
2098
+ }
2099
+ }
2100
+
2101
+ /** @import { Node } from 'estree' */
2102
+
2103
+ /**
2104
+ * @param {Node} node
2105
+ * @param {Node} parent
2106
+ * @returns {boolean}
2107
+ */
2108
+ function is_reference(node, parent) {
2109
+ if (node.type === 'MemberExpression') {
2110
+ return !node.computed && is_reference(node.object, node);
2111
+ }
2112
+
2113
+ if (node.type !== 'Identifier') return false;
2114
+
2115
+ switch (parent?.type) {
2116
+ // disregard `bar` in `foo.bar`
2117
+ case 'MemberExpression':
2118
+ return parent.computed || node === parent.object;
2119
+
2120
+ // disregard the `foo` in `class {foo(){}}` but keep it in `class {[foo](){}}`
2121
+ case 'MethodDefinition':
2122
+ return parent.computed;
2123
+
2124
+ // disregard the `meta` in `import.meta`
2125
+ case 'MetaProperty':
2126
+ return parent.meta === node;
2127
+
2128
+ // disregard the `foo` in `class {foo=bar}` but keep it in `class {[foo]=bar}` and `class {bar=foo}`
2129
+ case 'PropertyDefinition':
2130
+ return parent.computed || node === parent.value;
2131
+
2132
+ // disregard the `bar` in `{ bar: foo }`, but keep it in `{ [bar]: foo }`
2133
+ case 'Property':
2134
+ return parent.computed || node === parent.value;
2135
+
2136
+ // disregard the `bar` in `export { foo as bar }` or
2137
+ // the foo in `import { foo as bar }`
2138
+ case 'ExportSpecifier':
2139
+ case 'ImportSpecifier':
2140
+ return node === parent.local;
2141
+
2142
+ // disregard the `foo` in `foo: while (...) { ... break foo; ... continue foo;}`
2143
+ case 'LabeledStatement':
2144
+ case 'BreakStatement':
2145
+ case 'ContinueStatement':
2146
+ return false;
2147
+
2148
+ default:
2149
+ return true;
2150
+ }
2151
+ }
2152
+
2153
+ function createInclusionContext() {
2154
+ return {
2155
+ brokenFlow: false,
2156
+ hasBreak: false,
2157
+ hasContinue: false,
2158
+ includedCallArguments: new Set(),
2159
+ includedLabels: new Set()
2160
+ };
2161
+ }
2162
+ function createHasEffectsContext() {
2163
+ return {
2164
+ accessed: new EntityPathTracker(),
2165
+ assigned: new EntityPathTracker(),
2166
+ brokenFlow: false,
2167
+ called: new DiscriminatedPathTracker(),
2168
+ hasBreak: false,
2169
+ hasContinue: false,
2170
+ ignore: {
2171
+ breaks: false,
2172
+ continues: false,
2173
+ labels: new Set(),
2174
+ returnYield: false,
2175
+ this: false
2176
+ },
2177
+ includedLabels: new Set(),
2178
+ instantiated: new DiscriminatedPathTracker(),
2179
+ replacedVariableInits: new Map()
2180
+ };
2181
+ }
2116
2182
 
2117
2183
  function isFlagSet(flags, flag) {
2118
2184
  return (flags & flag) !== 0;
@@ -2152,12 +2218,25 @@ class ExpressionEntity {
2152
2218
  hasEffectsOnInteractionAtPath(_path, _interaction, _context) {
2153
2219
  return true;
2154
2220
  }
2155
- include(_context, _includeChildrenRecursively, _options) {
2221
+ include(context, _includeChildrenRecursively, _options) {
2222
+ if (!this.included)
2223
+ this.includeNode(context);
2224
+ }
2225
+ includeNode(_context) {
2156
2226
  this.included = true;
2157
2227
  }
2158
- includeCallArguments(context, parameters) {
2159
- for (const argument of parameters) {
2160
- argument.include(context, false);
2228
+ includePath(_path, context) {
2229
+ if (!this.included)
2230
+ this.includeNode(context);
2231
+ }
2232
+ /* We are both including and including an unknown path here as the former
2233
+ * ensures that nested nodes are included while the latter ensures that all
2234
+ * paths of the expression are included.
2235
+ * */
2236
+ includeCallArguments(context, interaction) {
2237
+ for (const argument of interaction.args) {
2238
+ argument?.includePath(UNKNOWN_PATH, context);
2239
+ argument?.include(context, false);
2161
2240
  }
2162
2241
  }
2163
2242
  shouldBeIncluded(_context) {
@@ -2196,6 +2275,19 @@ const NODE_INTERACTION_UNKNOWN_CALL = {
2196
2275
  withNew: false
2197
2276
  };
2198
2277
 
2278
+ const PureFunctionKey = Symbol('PureFunction');
2279
+ const getPureFunctions = ({ treeshake }) => {
2280
+ const pureFunctions = Object.create(null);
2281
+ for (const functionName of treeshake ? treeshake.manualPureFunctions : []) {
2282
+ let currentFunctions = pureFunctions;
2283
+ for (const pathSegment of functionName.split('.')) {
2284
+ currentFunctions = currentFunctions[pathSegment] ||= Object.create(null);
2285
+ }
2286
+ currentFunctions[PureFunctionKey] = true;
2287
+ }
2288
+ return pureFunctions;
2289
+ };
2290
+
2199
2291
  class Variable extends ExpressionEntity {
2200
2292
  markReassigned() {
2201
2293
  this.isReassigned = true;
@@ -2272,9 +2364,9 @@ class Variable extends ExpressionEntity {
2272
2364
  * has not been included previously. Once a variable is included, it should
2273
2365
  * take care all its declarations are included.
2274
2366
  */
2275
- include() {
2367
+ includePath(path, context) {
2276
2368
  this.included = true;
2277
- this.renderedLikeHoisted?.include();
2369
+ this.renderedLikeHoisted?.includePath(path, context);
2278
2370
  }
2279
2371
  /**
2280
2372
  * Links the rendered name of this variable to another variable and includes
@@ -2306,8 +2398,8 @@ class ExternalVariable extends Variable {
2306
2398
  hasEffectsOnInteractionAtPath(path, { type }) {
2307
2399
  return type !== INTERACTION_ACCESSED || path.length > (this.isNamespace ? 1 : 0);
2308
2400
  }
2309
- include() {
2310
- super.include();
2401
+ includePath(path, context) {
2402
+ super.includePath(path, context);
2311
2403
  this.module.used = true;
2312
2404
  }
2313
2405
  }
@@ -2608,36 +2700,6 @@ const childNodeKeys = {
2608
2700
  YieldExpression: ['argument']
2609
2701
  };
2610
2702
 
2611
- function createInclusionContext() {
2612
- return {
2613
- brokenFlow: false,
2614
- hasBreak: false,
2615
- hasContinue: false,
2616
- includedCallArguments: new Set(),
2617
- includedLabels: new Set()
2618
- };
2619
- }
2620
- function createHasEffectsContext() {
2621
- return {
2622
- accessed: new PathTracker(),
2623
- assigned: new PathTracker(),
2624
- brokenFlow: false,
2625
- called: new DiscriminatedPathTracker(),
2626
- hasBreak: false,
2627
- hasContinue: false,
2628
- ignore: {
2629
- breaks: false,
2630
- continues: false,
2631
- labels: new Set(),
2632
- returnYield: false,
2633
- this: false
2634
- },
2635
- includedLabels: new Set(),
2636
- instantiated: new DiscriminatedPathTracker(),
2637
- replacedVariableInits: new Map()
2638
- };
2639
- }
2640
-
2641
2703
  const INCLUDE_PARAMETERS = 'variables';
2642
2704
  const IS_SKIPPED_CHAIN = Symbol('IS_SKIPPED_CHAIN');
2643
2705
  class NodeBase extends ExpressionEntity {
@@ -2707,9 +2769,8 @@ class NodeBase extends ExpressionEntity {
2707
2769
  this.hasEffectsOnInteractionAtPath(EMPTY_PATH, this.assignmentInteraction, context));
2708
2770
  }
2709
2771
  include(context, includeChildrenRecursively, _options) {
2710
- if (!this.deoptimized)
2711
- this.applyDeoptimizations();
2712
- this.included = true;
2772
+ if (!this.included)
2773
+ this.includeNode(context);
2713
2774
  for (const key of childNodeKeys[this.type]) {
2714
2775
  const value = this[key];
2715
2776
  if (value === null)
@@ -2724,6 +2785,24 @@ class NodeBase extends ExpressionEntity {
2724
2785
  }
2725
2786
  }
2726
2787
  }
2788
+ includeNode(context) {
2789
+ this.included = true;
2790
+ if (!this.deoptimized)
2791
+ this.applyDeoptimizations();
2792
+ for (const key of childNodeKeys[this.type]) {
2793
+ const value = this[key];
2794
+ if (value === null)
2795
+ continue;
2796
+ if (Array.isArray(value)) {
2797
+ for (const child of value) {
2798
+ child?.includePath(UNKNOWN_PATH, context);
2799
+ }
2800
+ }
2801
+ else {
2802
+ value.includePath(UNKNOWN_PATH, context);
2803
+ }
2804
+ }
2805
+ }
2727
2806
  includeAsAssignmentTarget(context, includeChildrenRecursively, _deoptimizeAccess) {
2728
2807
  this.include(context, includeChildrenRecursively);
2729
2808
  }
@@ -2827,6 +2906,17 @@ class NodeBase extends ExpressionEntity {
2827
2906
  function createChildNodeKeysForNode(esTreeNode) {
2828
2907
  return Object.keys(esTreeNode).filter(key => typeof esTreeNode[key] === 'object' && key.charCodeAt(0) !== 95 /* _ */);
2829
2908
  }
2909
+ function onlyIncludeSelf() {
2910
+ this.included = true;
2911
+ if (!this.deoptimized)
2912
+ this.applyDeoptimizations();
2913
+ }
2914
+ function onlyIncludeSelfNoDeoptimize() {
2915
+ this.included = true;
2916
+ }
2917
+ function doNotDeoptimize() {
2918
+ this.deoptimized = true;
2919
+ }
2830
2920
 
2831
2921
  function isObjectExpressionNode(node) {
2832
2922
  return node instanceof NodeBase && node.type === ObjectExpression$1;
@@ -2839,8 +2929,8 @@ function assembleMemberDescriptions(memberDescriptions, inheritedDescriptions =
2839
2929
  return Object.create(inheritedDescriptions, memberDescriptions);
2840
2930
  }
2841
2931
  const UNDEFINED_EXPRESSION = new (class UndefinedExpression extends ExpressionEntity {
2842
- getLiteralValueAtPath() {
2843
- return undefined;
2932
+ getLiteralValueAtPath(path) {
2933
+ return path.length > 0 ? UnknownValue : undefined;
2844
2934
  }
2845
2935
  })();
2846
2936
  const returnsUnknown = {
@@ -3037,31 +3127,6 @@ function getMemberReturnExpressionWhenCalled(members, memberName) {
3037
3127
  return [members[memberName].returns, false];
3038
3128
  }
3039
3129
 
3040
- class SpreadElement extends NodeBase {
3041
- deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
3042
- if (path.length > 0) {
3043
- this.argument.deoptimizeArgumentsOnInteractionAtPath(interaction, UNKNOWN_PATH, recursionTracker);
3044
- }
3045
- }
3046
- hasEffects(context) {
3047
- if (!this.deoptimized)
3048
- this.applyDeoptimizations();
3049
- const { propertyReadSideEffects } = this.scope.context.options
3050
- .treeshake;
3051
- return (this.argument.hasEffects(context) ||
3052
- (propertyReadSideEffects &&
3053
- (propertyReadSideEffects === 'always' ||
3054
- this.argument.hasEffectsOnInteractionAtPath(UNKNOWN_PATH, NODE_INTERACTION_UNKNOWN_ACCESS, context))));
3055
- }
3056
- applyDeoptimizations() {
3057
- this.deoptimized = true;
3058
- // Only properties of properties of the argument could become subject to reassignment
3059
- // This will also reassign the return values of iterators
3060
- this.argument.deoptimizePath([UnknownKey, UnknownKey]);
3061
- this.scope.context.requestTreeshakingPass();
3062
- }
3063
- }
3064
-
3065
3130
  class Method extends ExpressionEntity {
3066
3131
  constructor(description) {
3067
3132
  super();
@@ -3187,6 +3252,7 @@ class ObjectEntity extends ExpressionEntity {
3187
3252
  this.unknownIntegerProps = [];
3188
3253
  this.unmatchableGetters = [];
3189
3254
  this.unmatchablePropertiesAndGetters = [];
3255
+ this.unmatchablePropertiesAndSetters = [];
3190
3256
  this.unmatchableSetters = [];
3191
3257
  if (Array.isArray(properties)) {
3192
3258
  this.buildPropertyMaps(properties);
@@ -3421,9 +3487,38 @@ class ObjectEntity extends ExpressionEntity {
3421
3487
  }
3422
3488
  return false;
3423
3489
  }
3490
+ include(context, includeChildrenRecursively) {
3491
+ this.included = true;
3492
+ for (const property of this.allProperties) {
3493
+ if (includeChildrenRecursively || property.shouldBeIncluded(context)) {
3494
+ property.include(context, includeChildrenRecursively);
3495
+ }
3496
+ }
3497
+ this.prototypeExpression?.include(context, includeChildrenRecursively);
3498
+ }
3499
+ includePath(path, context) {
3500
+ this.included = true;
3501
+ if (path.length === 0)
3502
+ return;
3503
+ const [key, ...subPath] = path;
3504
+ const [includedMembers, includedPath] = typeof key === 'string'
3505
+ ? [
3506
+ [
3507
+ ...new Set([
3508
+ ...(this.propertiesAndGettersByKey[key] || this.unmatchablePropertiesAndGetters),
3509
+ ...(this.propertiesAndSettersByKey[key] || this.unmatchablePropertiesAndSetters)
3510
+ ])
3511
+ ],
3512
+ subPath
3513
+ ]
3514
+ : [this.allProperties, UNKNOWN_PATH];
3515
+ for (const property of includedMembers) {
3516
+ property.includePath(includedPath, context);
3517
+ }
3518
+ this.prototypeExpression?.includePath(path, context);
3519
+ }
3424
3520
  buildPropertyMaps(properties) {
3425
- const { allProperties, propertiesAndGettersByKey, propertiesAndSettersByKey, settersByKey, gettersByKey, unknownIntegerProps, unmatchablePropertiesAndGetters, unmatchableGetters, unmatchableSetters } = this;
3426
- const unmatchablePropertiesAndSetters = [];
3521
+ const { allProperties, propertiesAndGettersByKey, propertiesAndSettersByKey, settersByKey, gettersByKey, unknownIntegerProps, unmatchablePropertiesAndGetters, unmatchablePropertiesAndSetters, unmatchableGetters, unmatchableSetters } = this;
3427
3522
  for (let index = properties.length - 1; index >= 0; index--) {
3428
3523
  const { key, kind, property } = properties[index];
3429
3524
  allProperties.push(property);
@@ -3693,6 +3788,37 @@ const ARRAY_PROTOTYPE = new ObjectEntity({
3693
3788
  values: METHOD_DEOPTS_SELF_RETURNS_UNKNOWN
3694
3789
  }, OBJECT_PROTOTYPE, true);
3695
3790
 
3791
+ class SpreadElement extends NodeBase {
3792
+ deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
3793
+ if (path.length > 0) {
3794
+ this.argument.deoptimizeArgumentsOnInteractionAtPath(interaction, UNKNOWN_PATH, recursionTracker);
3795
+ }
3796
+ }
3797
+ hasEffects(context) {
3798
+ if (!this.deoptimized)
3799
+ this.applyDeoptimizations();
3800
+ const { propertyReadSideEffects } = this.scope.context.options
3801
+ .treeshake;
3802
+ return (this.argument.hasEffects(context) ||
3803
+ (propertyReadSideEffects &&
3804
+ (propertyReadSideEffects === 'always' ||
3805
+ this.argument.hasEffectsOnInteractionAtPath(UNKNOWN_PATH, NODE_INTERACTION_UNKNOWN_ACCESS, context))));
3806
+ }
3807
+ includeNode(context) {
3808
+ this.included = true;
3809
+ if (!this.deoptimized)
3810
+ this.applyDeoptimizations();
3811
+ this.argument.includePath(UNKNOWN_PATH, context);
3812
+ }
3813
+ applyDeoptimizations() {
3814
+ this.deoptimized = true;
3815
+ // Only properties of properties of the argument could become subject to reassignment
3816
+ // This will also reassign the return values of iterators
3817
+ this.argument.deoptimizePath([UnknownKey, UnknownKey]);
3818
+ this.scope.context.requestTreeshakingPass();
3819
+ }
3820
+ }
3821
+
3696
3822
  class ArrayExpression extends NodeBase {
3697
3823
  constructor() {
3698
3824
  super(...arguments);
@@ -3713,6 +3839,16 @@ class ArrayExpression extends NodeBase {
3713
3839
  hasEffectsOnInteractionAtPath(path, interaction, context) {
3714
3840
  return this.getObjectEntity().hasEffectsOnInteractionAtPath(path, interaction, context);
3715
3841
  }
3842
+ includeNode(context) {
3843
+ this.included = true;
3844
+ if (!this.deoptimized)
3845
+ this.applyDeoptimizations();
3846
+ for (const element of this.elements) {
3847
+ if (element) {
3848
+ element?.includePath(UNKNOWN_PATH, context);
3849
+ }
3850
+ }
3851
+ }
3716
3852
  applyDeoptimizations() {
3717
3853
  this.deoptimized = true;
3718
3854
  let hasSpread = false;
@@ -4780,17 +4916,37 @@ class GlobalVariable extends Variable {
4780
4916
  }
4781
4917
  }
4782
4918
 
4919
+ // To avoid infinite recursions
4920
+ const MAX_PATH_DEPTH = 6;
4921
+ // If a path is longer than MAX_PATH_DEPTH, it is truncated so that it is at
4922
+ // most MAX_PATH_DEPTH long. The last element is always UnknownKey
4923
+ const limitConcatenatedPathDepth = (path1, path2) => {
4924
+ const { length: length1 } = path1;
4925
+ const { length: length2 } = path2;
4926
+ return length1 === 0
4927
+ ? path2
4928
+ : length2 === 0
4929
+ ? path1
4930
+ : length1 + length2 > MAX_PATH_DEPTH
4931
+ ? [...path1, ...path2.slice(0, MAX_PATH_DEPTH - 1 - path1.length), 'UnknownKey']
4932
+ : [...path1, ...path2];
4933
+ };
4934
+
4783
4935
  class LocalVariable extends Variable {
4784
- constructor(name, declarator, init, context, kind) {
4936
+ constructor(name, declarator, init,
4937
+ /** if this is non-empty, the actual init is this path of this.init */
4938
+ initPath, context, kind) {
4785
4939
  super(name);
4786
4940
  this.init = init;
4941
+ this.initPath = initPath;
4942
+ this.kind = kind;
4787
4943
  this.calledFromTryStatement = false;
4788
4944
  this.additionalInitializers = null;
4945
+ this.includedPathTracker = new IncludedPathTracker();
4789
4946
  this.expressionsToBeDeoptimized = [];
4790
4947
  this.declarations = declarator ? [declarator] : [];
4791
4948
  this.deoptimizationTracker = context.deoptimizationTracker;
4792
4949
  this.module = context.module;
4793
- this.kind = kind;
4794
4950
  }
4795
4951
  addDeclaration(identifier, init) {
4796
4952
  this.declarations.push(identifier);
@@ -4801,15 +4957,16 @@ class LocalVariable extends Variable {
4801
4957
  for (const initializer of this.additionalInitializers) {
4802
4958
  initializer.deoptimizePath(UNKNOWN_PATH);
4803
4959
  }
4804
- this.additionalInitializers = null;
4805
4960
  }
4806
4961
  }
4807
4962
  deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
4808
- if (this.isReassigned) {
4963
+ if (this.isReassigned || path.length + this.initPath.length > MAX_PATH_DEPTH) {
4809
4964
  deoptimizeInteraction(interaction);
4810
4965
  return;
4811
4966
  }
4812
- recursionTracker.withTrackedEntityAtPath(path, this.init, () => this.init.deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker), undefined);
4967
+ recursionTracker.withTrackedEntityAtPath(path, this.init, () => {
4968
+ this.init.deoptimizeArgumentsOnInteractionAtPath(interaction, [...this.initPath, ...path], recursionTracker);
4969
+ }, undefined);
4813
4970
  }
4814
4971
  deoptimizePath(path) {
4815
4972
  if (this.isReassigned ||
@@ -4823,37 +4980,40 @@ class LocalVariable extends Variable {
4823
4980
  for (const expression of expressionsToBeDeoptimized) {
4824
4981
  expression.deoptimizeCache();
4825
4982
  }
4826
- this.init.deoptimizePath(UNKNOWN_PATH);
4983
+ this.init.deoptimizePath([...this.initPath, UnknownKey]);
4827
4984
  }
4828
4985
  else {
4829
- this.init.deoptimizePath(path);
4986
+ this.init.deoptimizePath(limitConcatenatedPathDepth(this.initPath, path));
4830
4987
  }
4831
4988
  }
4832
4989
  getLiteralValueAtPath(path, recursionTracker, origin) {
4833
- if (this.isReassigned) {
4990
+ if (this.isReassigned || path.length + this.initPath.length > MAX_PATH_DEPTH) {
4834
4991
  return UnknownValue;
4835
4992
  }
4836
4993
  return recursionTracker.withTrackedEntityAtPath(path, this.init, () => {
4837
4994
  this.expressionsToBeDeoptimized.push(origin);
4838
- return this.init.getLiteralValueAtPath(path, recursionTracker, origin);
4995
+ return this.init.getLiteralValueAtPath([...this.initPath, ...path], recursionTracker, origin);
4839
4996
  }, UnknownValue);
4840
4997
  }
4841
4998
  getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin) {
4842
- if (this.isReassigned) {
4999
+ if (this.isReassigned || path.length + this.initPath.length > MAX_PATH_DEPTH) {
4843
5000
  return UNKNOWN_RETURN_EXPRESSION;
4844
5001
  }
4845
5002
  return recursionTracker.withTrackedEntityAtPath(path, this.init, () => {
4846
5003
  this.expressionsToBeDeoptimized.push(origin);
4847
- return this.init.getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin);
5004
+ return this.init.getReturnExpressionWhenCalledAtPath([...this.initPath, ...path], interaction, recursionTracker, origin);
4848
5005
  }, UNKNOWN_RETURN_EXPRESSION);
4849
5006
  }
4850
5007
  hasEffectsOnInteractionAtPath(path, interaction, context) {
5008
+ if (path.length + this.initPath.length > MAX_PATH_DEPTH) {
5009
+ return true;
5010
+ }
4851
5011
  switch (interaction.type) {
4852
5012
  case INTERACTION_ACCESSED: {
4853
5013
  if (this.isReassigned)
4854
5014
  return true;
4855
5015
  return (!context.accessed.trackEntityAtPathAndGetIfTracked(path, this) &&
4856
- this.init.hasEffectsOnInteractionAtPath(path, interaction, context));
5016
+ this.init.hasEffectsOnInteractionAtPath([...this.initPath, ...path], interaction, context));
4857
5017
  }
4858
5018
  case INTERACTION_ASSIGNED: {
4859
5019
  if (this.included)
@@ -4863,44 +5023,63 @@ class LocalVariable extends Variable {
4863
5023
  if (this.isReassigned)
4864
5024
  return true;
4865
5025
  return (!context.assigned.trackEntityAtPathAndGetIfTracked(path, this) &&
4866
- this.init.hasEffectsOnInteractionAtPath(path, interaction, context));
5026
+ this.init.hasEffectsOnInteractionAtPath([...this.initPath, ...path], interaction, context));
4867
5027
  }
4868
5028
  case INTERACTION_CALLED: {
4869
5029
  if (this.isReassigned)
4870
5030
  return true;
4871
5031
  return (!(interaction.withNew ? context.instantiated : context.called).trackEntityAtPathAndGetIfTracked(path, interaction.args, this) &&
4872
- this.init.hasEffectsOnInteractionAtPath(path, interaction, context));
5032
+ this.init.hasEffectsOnInteractionAtPath([...this.initPath, ...path], interaction, context));
4873
5033
  }
4874
5034
  }
4875
5035
  }
4876
- include() {
4877
- if (!this.included) {
4878
- super.include();
5036
+ includePath(path, context) {
5037
+ if (!this.includedPathTracker.includePathAndGetIfIncluded(path)) {
5038
+ this.module.scope.context.requestTreeshakingPass();
5039
+ if (!this.included) {
5040
+ // This will reduce the number of tree-shaking passes by eagerly
5041
+ // including inits. By pushing this here instead of directly including
5042
+ // we avoid deep call stacks.
5043
+ this.module.scope.context.newlyIncludedVariableInits.add(this.init);
5044
+ }
5045
+ super.includePath(path, context);
4879
5046
  for (const declaration of this.declarations) {
4880
5047
  // If node is a default export, it can save a tree-shaking run to include the full declaration now
4881
5048
  if (!declaration.included)
4882
- declaration.include(createInclusionContext(), false);
5049
+ declaration.include(context, false);
4883
5050
  let node = declaration.parent;
4884
5051
  while (!node.included) {
4885
5052
  // We do not want to properly include parents in case they are part of a dead branch
4886
5053
  // in which case .include() might pull in more dead code
4887
- node.included = true;
5054
+ node.includeNode(context);
4888
5055
  if (node.type === Program$1)
4889
5056
  break;
4890
5057
  node = node.parent;
4891
5058
  }
4892
5059
  }
5060
+ // We need to make sure we include the correct path of the init
5061
+ if (path.length > 0) {
5062
+ this.init.includePath(limitConcatenatedPathDepth(this.initPath, path), context);
5063
+ this.additionalInitializers?.forEach(initializer => initializer.includePath(UNKNOWN_PATH, context));
5064
+ }
4893
5065
  }
4894
5066
  }
4895
- includeCallArguments(context, parameters) {
4896
- if (this.isReassigned || context.includedCallArguments.has(this.init)) {
4897
- for (const argument of parameters) {
4898
- argument.include(context, false);
5067
+ includeCallArguments(context, interaction) {
5068
+ if (this.isReassigned ||
5069
+ context.includedCallArguments.has(this.init) ||
5070
+ // This can be removed again once we can include arguments when called at
5071
+ // a specific path
5072
+ this.initPath.length > 0) {
5073
+ for (const argument of interaction.args) {
5074
+ if (argument) {
5075
+ argument.includePath(UNKNOWN_PATH, context);
5076
+ argument.include(context, false);
5077
+ }
4899
5078
  }
4900
5079
  }
4901
5080
  else {
4902
5081
  context.includedCallArguments.add(this.init);
4903
- this.init.includeCallArguments(context, parameters);
5082
+ this.init.includeCallArguments(context, interaction);
4904
5083
  context.includedCallArguments.delete(this.init);
4905
5084
  }
4906
5085
  }
@@ -4980,18 +5159,31 @@ class IdentifierBase extends NodeBase {
4980
5159
  }
4981
5160
  }
4982
5161
  }
4983
- include() {
5162
+ include(context) {
5163
+ if (!this.included)
5164
+ this.includeNode(context);
5165
+ }
5166
+ includeNode(context) {
5167
+ this.included = true;
4984
5168
  if (!this.deoptimized)
4985
5169
  this.applyDeoptimizations();
5170
+ if (this.variable !== null) {
5171
+ this.scope.context.includeVariableInModule(this.variable, EMPTY_PATH, context);
5172
+ }
5173
+ }
5174
+ includePath(path, context) {
4986
5175
  if (!this.included) {
4987
5176
  this.included = true;
4988
5177
  if (this.variable !== null) {
4989
- this.scope.context.includeVariableInModule(this.variable);
5178
+ this.scope.context.includeVariableInModule(this.variable, path, context);
4990
5179
  }
4991
5180
  }
5181
+ else if (path.length > 0) {
5182
+ this.variable?.includePath(path, context);
5183
+ }
4992
5184
  }
4993
- includeCallArguments(context, parameters) {
4994
- this.variable.includeCallArguments(context, parameters);
5185
+ includeCallArguments(context, interaction) {
5186
+ this.variable.includeCallArguments(context, interaction);
4995
5187
  }
4996
5188
  isPossibleTDZ() {
4997
5189
  // return cached value to avoid issues with the next tree-shaking pass
@@ -5070,8 +5262,31 @@ function closestParentFunctionOrProgram(node) {
5070
5262
  while (node && !/^Program|Function/.test(node.type)) {
5071
5263
  node = node.parent;
5072
5264
  }
5073
- // one of: ArrowFunctionExpression, FunctionDeclaration, FunctionExpression or Program
5074
- return node;
5265
+ // one of: ArrowFunctionExpression, FunctionDeclaration, FunctionExpression or Program
5266
+ return node;
5267
+ }
5268
+
5269
+ class ObjectMember extends ExpressionEntity {
5270
+ constructor(object, path) {
5271
+ super();
5272
+ this.object = object;
5273
+ this.path = path;
5274
+ }
5275
+ deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
5276
+ this.object.deoptimizeArgumentsOnInteractionAtPath(interaction, [...this.path, ...path], recursionTracker);
5277
+ }
5278
+ deoptimizePath(path) {
5279
+ this.object.deoptimizePath([...this.path, ...path]);
5280
+ }
5281
+ getLiteralValueAtPath(path, recursionTracker, origin) {
5282
+ return this.object.getLiteralValueAtPath([...this.path, ...path], recursionTracker, origin);
5283
+ }
5284
+ getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin) {
5285
+ return this.object.getReturnExpressionWhenCalledAtPath([...this.path, ...path], interaction, recursionTracker, origin);
5286
+ }
5287
+ hasEffectsOnInteractionAtPath(path, interaction, context) {
5288
+ return this.object.hasEffectsOnInteractionAtPath([...this.path, ...path], interaction, context);
5289
+ }
5075
5290
  }
5076
5291
 
5077
5292
  class Identifier extends IdentifierBase {
@@ -5079,6 +5294,12 @@ class Identifier extends IdentifierBase {
5079
5294
  super(...arguments);
5080
5295
  this.variable = null;
5081
5296
  }
5297
+ get isDestructuringDeoptimized() {
5298
+ return isFlagSet(this.flags, 16777216 /* Flag.destructuringDeoptimized */);
5299
+ }
5300
+ set isDestructuringDeoptimized(value) {
5301
+ this.flags = setFlag(this.flags, 16777216 /* Flag.destructuringDeoptimized */, value);
5302
+ }
5082
5303
  addExportedVariables(variables, exportNamesByVariable) {
5083
5304
  if (exportNamesByVariable.has(this.variable)) {
5084
5305
  variables.push(this.variable);
@@ -5091,43 +5312,53 @@ class Identifier extends IdentifierBase {
5091
5312
  this.isVariableReference = true;
5092
5313
  }
5093
5314
  }
5094
- declare(kind, init) {
5315
+ declare(kind, destructuredInitPath, init) {
5095
5316
  let variable;
5096
5317
  const { treeshake } = this.scope.context.options;
5097
- switch (kind) {
5098
- case 'var': {
5099
- variable = this.scope.addDeclaration(this, this.scope.context, init, kind);
5100
- if (treeshake && treeshake.correctVarValueBeforeDeclaration) {
5101
- // Necessary to make sure the init is deoptimized. We cannot call deoptimizePath here.
5102
- variable.markInitializersForDeoptimization();
5103
- }
5104
- break;
5105
- }
5106
- case 'function': {
5107
- // in strict mode, functions are only hoisted within a scope but not across block scopes
5108
- variable = this.scope.addDeclaration(this, this.scope.context, init, kind);
5109
- break;
5110
- }
5111
- case 'let':
5112
- case 'const':
5113
- case 'using':
5114
- case 'await using':
5115
- case 'class': {
5116
- variable = this.scope.addDeclaration(this, this.scope.context, init, kind);
5117
- break;
5118
- }
5119
- case 'parameter': {
5120
- variable = this.scope.addParameterDeclaration(this);
5121
- break;
5122
- }
5123
- /* istanbul ignore next */
5124
- default: {
5125
- /* istanbul ignore next */
5126
- throw new Error(`Internal Error: Unexpected identifier kind ${kind}.`);
5318
+ if (kind === 'parameter') {
5319
+ variable = this.scope.addParameterDeclaration(this, destructuredInitPath);
5320
+ }
5321
+ else {
5322
+ variable = this.scope.addDeclaration(this, this.scope.context, init, destructuredInitPath, kind);
5323
+ if (kind === 'var' && treeshake && treeshake.correctVarValueBeforeDeclaration) {
5324
+ // Necessary to make sure the init is deoptimized. We cannot call deoptimizePath here.
5325
+ variable.markInitializersForDeoptimization();
5127
5326
  }
5128
5327
  }
5129
5328
  return [(this.variable = variable)];
5130
5329
  }
5330
+ deoptimizeAssignment(destructuredInitPath, init) {
5331
+ this.deoptimizePath(EMPTY_PATH);
5332
+ init.deoptimizePath([...destructuredInitPath, UnknownKey]);
5333
+ }
5334
+ hasEffectsWhenDestructuring(context, destructuredInitPath, init) {
5335
+ return (destructuredInitPath.length > 0 &&
5336
+ init.hasEffectsOnInteractionAtPath(destructuredInitPath, NODE_INTERACTION_UNKNOWN_ACCESS, context));
5337
+ }
5338
+ includeDestructuredIfNecessary(context, destructuredInitPath, init) {
5339
+ if (destructuredInitPath.length > 0 && !this.isDestructuringDeoptimized) {
5340
+ this.isDestructuringDeoptimized = true;
5341
+ init.deoptimizeArgumentsOnInteractionAtPath({
5342
+ args: [new ObjectMember(init, destructuredInitPath.slice(0, -1))],
5343
+ type: INTERACTION_ACCESSED
5344
+ }, destructuredInitPath, SHARED_RECURSION_TRACKER);
5345
+ }
5346
+ const { propertyReadSideEffects } = this.scope.context.options
5347
+ .treeshake;
5348
+ if ((this.included ||=
5349
+ destructuredInitPath.length > 0 &&
5350
+ !context.brokenFlow &&
5351
+ propertyReadSideEffects &&
5352
+ (propertyReadSideEffects === 'always' ||
5353
+ init.hasEffectsOnInteractionAtPath(destructuredInitPath, NODE_INTERACTION_UNKNOWN_ACCESS, createHasEffectsContext())))) {
5354
+ if (this.variable && !this.variable.included) {
5355
+ this.scope.context.includeVariableInModule(this.variable, EMPTY_PATH, context);
5356
+ }
5357
+ init.includePath(destructuredInitPath, context);
5358
+ return true;
5359
+ }
5360
+ return false;
5361
+ }
5131
5362
  markDeclarationReached() {
5132
5363
  this.variable.initReached = true;
5133
5364
  }
@@ -5192,18 +5423,17 @@ class Scope {
5192
5423
  - then the variable is still declared in the hoisted outer scope, but the initializer is assigned to the parameter
5193
5424
  - const, let, class, and function except in the cases above cannot redeclare anything
5194
5425
  */
5195
- addDeclaration(identifier, context, init, kind) {
5426
+ addDeclaration(identifier, context, init, destructuredInitPath, kind) {
5196
5427
  const name = identifier.name;
5197
5428
  const existingVariable = this.hoistedVariables?.get(name) || this.variables.get(name);
5198
5429
  if (existingVariable) {
5199
- const existingKind = existingVariable.kind;
5200
- if (kind === 'var' && existingKind === 'var') {
5430
+ if (kind === 'var' && existingVariable.kind === 'var') {
5201
5431
  existingVariable.addDeclaration(identifier, init);
5202
5432
  return existingVariable;
5203
5433
  }
5204
5434
  context.error(logRedeclarationError(name), identifier.start);
5205
5435
  }
5206
- const newVariable = new LocalVariable(identifier.name, identifier, init, context, kind);
5436
+ const newVariable = new LocalVariable(identifier.name, identifier, init, destructuredInitPath, context, kind);
5207
5437
  this.variables.set(name, newVariable);
5208
5438
  return newVariable;
5209
5439
  }
@@ -5379,7 +5609,6 @@ class MethodBase extends NodeBase {
5379
5609
  }
5380
5610
  return this.getAccessedValue()[0].hasEffectsOnInteractionAtPath(path, interaction, context);
5381
5611
  }
5382
- applyDeoptimizations() { }
5383
5612
  getAccessedValue() {
5384
5613
  if (this.accessedValue === null) {
5385
5614
  if (this.kind === 'get') {
@@ -5393,19 +5622,20 @@ class MethodBase extends NodeBase {
5393
5622
  return this.accessedValue;
5394
5623
  }
5395
5624
  }
5625
+ MethodBase.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
5626
+ MethodBase.prototype.applyDeoptimizations = doNotDeoptimize;
5396
5627
 
5397
5628
  class MethodDefinition extends MethodBase {
5398
5629
  hasEffects(context) {
5399
5630
  return super.hasEffects(context) || checkEffectForNodes(this.decorators, context);
5400
5631
  }
5401
- applyDeoptimizations() { }
5402
5632
  }
5403
5633
 
5404
5634
  class BlockScope extends ChildScope {
5405
5635
  constructor(parent) {
5406
5636
  super(parent, parent.context);
5407
5637
  }
5408
- addDeclaration(identifier, context, init, kind) {
5638
+ addDeclaration(identifier, context, init, destructuredInitPath, kind) {
5409
5639
  if (kind === 'var') {
5410
5640
  const name = identifier.name;
5411
5641
  const existingVariable = this.hoistedVariables?.get(name) || this.variables.get(name);
@@ -5417,7 +5647,7 @@ class BlockScope extends ChildScope {
5417
5647
  }
5418
5648
  return context.error(logRedeclarationError(name), identifier.start);
5419
5649
  }
5420
- const declaredVariable = this.parent.addDeclaration(identifier, context, init, kind);
5650
+ const declaredVariable = this.parent.addDeclaration(identifier, context, init, destructuredInitPath, kind);
5421
5651
  // Necessary to make sure the init is deoptimized for conditional declarations.
5422
5652
  // We cannot call deoptimizePath here.
5423
5653
  declaredVariable.markInitializersForDeoptimization();
@@ -5425,7 +5655,7 @@ class BlockScope extends ChildScope {
5425
5655
  this.addHoistedVariable(name, declaredVariable);
5426
5656
  return declaredVariable;
5427
5657
  }
5428
- return super.addDeclaration(identifier, context, init, kind);
5658
+ return super.addDeclaration(identifier, context, init, destructuredInitPath, kind);
5429
5659
  }
5430
5660
  }
5431
5661
 
@@ -5457,33 +5687,12 @@ class StaticBlock extends NodeBase {
5457
5687
  }
5458
5688
  }
5459
5689
  }
5690
+ StaticBlock.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
5691
+ StaticBlock.prototype.applyDeoptimizations = doNotDeoptimize;
5460
5692
  function isStaticBlock(statement) {
5461
5693
  return statement.type === StaticBlock$1;
5462
5694
  }
5463
5695
 
5464
- class ObjectMember extends ExpressionEntity {
5465
- constructor(object, key) {
5466
- super();
5467
- this.object = object;
5468
- this.key = key;
5469
- }
5470
- deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
5471
- this.object.deoptimizeArgumentsOnInteractionAtPath(interaction, [this.key, ...path], recursionTracker);
5472
- }
5473
- deoptimizePath(path) {
5474
- this.object.deoptimizePath([this.key, ...path]);
5475
- }
5476
- getLiteralValueAtPath(path, recursionTracker, origin) {
5477
- return this.object.getLiteralValueAtPath([this.key, ...path], recursionTracker, origin);
5478
- }
5479
- getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin) {
5480
- return this.object.getReturnExpressionWhenCalledAtPath([this.key, ...path], interaction, recursionTracker, origin);
5481
- }
5482
- hasEffectsOnInteractionAtPath(path, interaction, context) {
5483
- return this.object.hasEffectsOnInteractionAtPath([this.key, ...path], interaction, context);
5484
- }
5485
- }
5486
-
5487
5696
  class ClassNode extends NodeBase {
5488
5697
  constructor() {
5489
5698
  super(...arguments);
@@ -5524,21 +5733,20 @@ class ClassNode extends NodeBase {
5524
5733
  : this.getObjectEntity().hasEffectsOnInteractionAtPath(path, interaction, context);
5525
5734
  }
5526
5735
  include(context, includeChildrenRecursively) {
5527
- if (!this.deoptimized)
5528
- this.applyDeoptimizations();
5529
- this.included = true;
5736
+ if (!this.included)
5737
+ this.includeNode(context);
5530
5738
  this.superClass?.include(context, includeChildrenRecursively);
5531
5739
  this.body.include(context, includeChildrenRecursively);
5532
5740
  for (const decorator of this.decorators)
5533
5741
  decorator.include(context, includeChildrenRecursively);
5534
5742
  if (this.id) {
5535
5743
  this.id.markDeclarationReached();
5536
- this.id.include();
5744
+ this.id.include(context);
5537
5745
  }
5538
5746
  }
5539
5747
  initialise() {
5540
5748
  super.initialise();
5541
- this.id?.declare('class', this);
5749
+ this.id?.declare('class', EMPTY_PATH, this);
5542
5750
  for (const method of this.body.body) {
5543
5751
  if (method instanceof MethodDefinition && method.kind === 'constructor') {
5544
5752
  this.classConstructor = method;
@@ -5596,11 +5804,12 @@ class ClassNode extends NodeBase {
5596
5804
  staticProperties.unshift({
5597
5805
  key: 'prototype',
5598
5806
  kind: 'init',
5599
- property: new ObjectEntity(dynamicMethods, this.superClass ? new ObjectMember(this.superClass, 'prototype') : OBJECT_PROTOTYPE)
5807
+ property: new ObjectEntity(dynamicMethods, this.superClass ? new ObjectMember(this.superClass, ['prototype']) : OBJECT_PROTOTYPE)
5600
5808
  });
5601
5809
  return (this.objectEntity = new ObjectEntity(staticProperties, this.superClass || OBJECT_PROTOTYPE));
5602
5810
  }
5603
5811
  }
5812
+ ClassNode.prototype.includeNode = onlyIncludeSelf;
5604
5813
 
5605
5814
  class ClassDeclaration extends ClassNode {
5606
5815
  initialise() {
@@ -5653,7 +5862,7 @@ class ClassDeclaration extends ClassNode {
5653
5862
 
5654
5863
  class ArgumentsVariable extends LocalVariable {
5655
5864
  constructor(context) {
5656
- super('arguments', null, UNKNOWN_EXPRESSION, context, 'other');
5865
+ super('arguments', null, UNKNOWN_EXPRESSION, EMPTY_PATH, context, 'other');
5657
5866
  this.deoptimizedArguments = [];
5658
5867
  }
5659
5868
  addArgumentToBeDeoptimized(argument) {
@@ -5667,8 +5876,8 @@ class ArgumentsVariable extends LocalVariable {
5667
5876
  hasEffectsOnInteractionAtPath(path, { type }) {
5668
5877
  return type !== INTERACTION_ACCESSED || path.length > 1;
5669
5878
  }
5670
- include() {
5671
- super.include();
5879
+ includePath(path, context) {
5880
+ super.includePath(path, context);
5672
5881
  for (const argument of this.deoptimizedArguments) {
5673
5882
  argument.deoptimizePath(UNKNOWN_PATH);
5674
5883
  }
@@ -5679,27 +5888,28 @@ class ArgumentsVariable extends LocalVariable {
5679
5888
  const MAX_TRACKED_INTERACTIONS = 20;
5680
5889
  const NO_INTERACTIONS = EMPTY_ARRAY;
5681
5890
  const UNKNOWN_DEOPTIMIZED_FIELD = new Set([UnknownKey]);
5682
- const EMPTY_PATH_TRACKER = new PathTracker();
5891
+ const EMPTY_PATH_TRACKER = new EntityPathTracker();
5683
5892
  const UNKNOWN_DEOPTIMIZED_ENTITY = new Set([UNKNOWN_EXPRESSION]);
5684
5893
  class ParameterVariable extends LocalVariable {
5685
- constructor(name, declarator, context) {
5686
- super(name, declarator, UNKNOWN_EXPRESSION, context, 'parameter');
5894
+ constructor(name, declarator, argumentPath, context) {
5895
+ super(name, declarator, UNKNOWN_EXPRESSION, argumentPath, context, 'parameter');
5687
5896
  this.deoptimizationInteractions = [];
5688
- this.deoptimizations = new PathTracker();
5897
+ this.deoptimizations = new EntityPathTracker();
5689
5898
  this.deoptimizedFields = new Set();
5690
- this.entitiesToBeDeoptimized = new Set();
5691
- this.expressionsUseTheKnownValue = [];
5899
+ this.argumentsToBeDeoptimized = new Set();
5900
+ this.expressionsDependingOnKnownValue = [];
5692
5901
  this.knownValue = null;
5693
5902
  this.knownValueLiteral = UnknownValue;
5694
5903
  this.frozenValue = null;
5695
5904
  }
5696
- addEntityToBeDeoptimized(entity) {
5905
+ addArgumentValue(entity) {
5906
+ this.updateKnownValue(entity);
5697
5907
  if (entity === UNKNOWN_EXPRESSION) {
5698
5908
  // As unknown expressions fully deoptimize all interactions, we can clear
5699
5909
  // the interaction cache at this point provided we keep this optimization
5700
5910
  // in mind when adding new interactions
5701
- if (!this.entitiesToBeDeoptimized.has(UNKNOWN_EXPRESSION)) {
5702
- this.entitiesToBeDeoptimized.add(UNKNOWN_EXPRESSION);
5911
+ if (!this.argumentsToBeDeoptimized.has(UNKNOWN_EXPRESSION)) {
5912
+ this.argumentsToBeDeoptimized.add(UNKNOWN_EXPRESSION);
5703
5913
  for (const { interaction } of this.deoptimizationInteractions) {
5704
5914
  deoptimizeInteraction(interaction);
5705
5915
  }
@@ -5709,27 +5919,34 @@ class ParameterVariable extends LocalVariable {
5709
5919
  else if (this.deoptimizedFields.has(UnknownKey)) {
5710
5920
  // This means that we already deoptimized all interactions and no longer
5711
5921
  // track them
5712
- entity.deoptimizePath(UNKNOWN_PATH);
5922
+ entity.deoptimizePath([...this.initPath, UnknownKey]);
5713
5923
  }
5714
- else if (!this.entitiesToBeDeoptimized.has(entity)) {
5715
- this.entitiesToBeDeoptimized.add(entity);
5924
+ else if (!this.argumentsToBeDeoptimized.has(entity)) {
5925
+ this.argumentsToBeDeoptimized.add(entity);
5716
5926
  for (const field of this.deoptimizedFields) {
5717
- entity.deoptimizePath([field]);
5927
+ entity.deoptimizePath([...this.initPath, field]);
5718
5928
  }
5719
5929
  for (const { interaction, path } of this.deoptimizationInteractions) {
5720
- entity.deoptimizeArgumentsOnInteractionAtPath(interaction, path, SHARED_RECURSION_TRACKER);
5930
+ if (this.initPath.length + path.length > MAX_PATH_DEPTH) {
5931
+ deoptimizeInteraction(interaction);
5932
+ continue;
5933
+ }
5934
+ entity.deoptimizeArgumentsOnInteractionAtPath(interaction, [...this.initPath, ...path], SHARED_RECURSION_TRACKER);
5721
5935
  }
5722
5936
  }
5723
5937
  }
5938
+ /** This says we should not make assumptions about the value of the parameter.
5939
+ * This is different from deoptimization that will also cause argument values
5940
+ * to be deoptimized. */
5724
5941
  markReassigned() {
5725
5942
  if (this.isReassigned) {
5726
5943
  return;
5727
5944
  }
5728
5945
  super.markReassigned();
5729
- for (const expression of this.expressionsUseTheKnownValue) {
5946
+ for (const expression of this.expressionsDependingOnKnownValue) {
5730
5947
  expression.deoptimizeCache();
5731
5948
  }
5732
- this.expressionsUseTheKnownValue = EMPTY_ARRAY;
5949
+ this.expressionsDependingOnKnownValue = EMPTY_ARRAY;
5733
5950
  }
5734
5951
  deoptimizeCache() {
5735
5952
  this.markReassigned();
@@ -5746,7 +5963,7 @@ class ParameterVariable extends LocalVariable {
5746
5963
  }
5747
5964
  if (this.knownValue === null) {
5748
5965
  this.knownValue = argument;
5749
- this.knownValueLiteral = argument.getLiteralValueAtPath(EMPTY_PATH, SHARED_RECURSION_TRACKER, this);
5966
+ this.knownValueLiteral = argument.getLiteralValueAtPath(this.initPath, SHARED_RECURSION_TRACKER, this);
5750
5967
  return;
5751
5968
  }
5752
5969
  // the same literal or identifier, do nothing
@@ -5762,7 +5979,7 @@ class ParameterVariable extends LocalVariable {
5762
5979
  return;
5763
5980
  }
5764
5981
  // add tracking for the new argument
5765
- const newValue = argument.getLiteralValueAtPath(EMPTY_PATH, SHARED_RECURSION_TRACKER, this);
5982
+ const newValue = argument.getLiteralValueAtPath(this.initPath, SHARED_RECURSION_TRACKER, this);
5766
5983
  if (newValue !== oldValue) {
5767
5984
  this.markReassigned();
5768
5985
  }
@@ -5780,24 +5997,31 @@ class ParameterVariable extends LocalVariable {
5780
5997
  return this.frozenValue;
5781
5998
  }
5782
5999
  getLiteralValueAtPath(path, recursionTracker, origin) {
5783
- if (this.isReassigned) {
6000
+ if (this.isReassigned || path.length + this.initPath.length > MAX_PATH_DEPTH) {
5784
6001
  return UnknownValue;
5785
6002
  }
5786
6003
  const knownValue = this.getKnownValue();
5787
- this.expressionsUseTheKnownValue.push(origin);
5788
- return recursionTracker.withTrackedEntityAtPath(path, knownValue, () => knownValue.getLiteralValueAtPath(path, recursionTracker, origin), UnknownValue);
6004
+ this.expressionsDependingOnKnownValue.push(origin);
6005
+ return recursionTracker.withTrackedEntityAtPath(path, knownValue, () => knownValue.getLiteralValueAtPath([...this.initPath, ...path], recursionTracker, origin), UnknownValue);
5789
6006
  }
5790
6007
  hasEffectsOnInteractionAtPath(path, interaction, context) {
5791
- if (this.isReassigned || interaction.type === INTERACTION_ASSIGNED) {
6008
+ const { type } = interaction;
6009
+ if (this.isReassigned ||
6010
+ type === INTERACTION_ASSIGNED ||
6011
+ path.length + this.initPath.length > MAX_PATH_DEPTH) {
5792
6012
  return super.hasEffectsOnInteractionAtPath(path, interaction, context);
5793
6013
  }
5794
- const knownValue = this.getKnownValue();
5795
- return knownValue.hasEffectsOnInteractionAtPath(path, interaction, context);
6014
+ return (!(type === INTERACTION_CALLED
6015
+ ? (interaction.withNew
6016
+ ? context.instantiated
6017
+ : context.called).trackEntityAtPathAndGetIfTracked(path, interaction.args, this)
6018
+ : context.accessed.trackEntityAtPathAndGetIfTracked(path, this)) &&
6019
+ this.getKnownValue().hasEffectsOnInteractionAtPath([...this.initPath, ...path], interaction, context));
5796
6020
  }
5797
6021
  deoptimizeArgumentsOnInteractionAtPath(interaction, path) {
5798
6022
  // For performance reasons, we fully deoptimize all deeper interactions
5799
6023
  if (path.length >= 2 ||
5800
- this.entitiesToBeDeoptimized.has(UNKNOWN_EXPRESSION) ||
6024
+ this.argumentsToBeDeoptimized.has(UNKNOWN_EXPRESSION) ||
5801
6025
  this.deoptimizationInteractions.length >= MAX_TRACKED_INTERACTIONS ||
5802
6026
  (path.length === 1 &&
5803
6027
  (this.deoptimizedFields.has(UnknownKey) ||
@@ -5806,10 +6030,10 @@ class ParameterVariable extends LocalVariable {
5806
6030
  return;
5807
6031
  }
5808
6032
  if (!this.deoptimizations.trackEntityAtPathAndGetIfTracked(path, interaction.args)) {
5809
- for (const entity of this.entitiesToBeDeoptimized) {
5810
- entity.deoptimizeArgumentsOnInteractionAtPath(interaction, path, SHARED_RECURSION_TRACKER);
6033
+ for (const entity of this.argumentsToBeDeoptimized) {
6034
+ entity.deoptimizeArgumentsOnInteractionAtPath(interaction, [...this.initPath, ...path], SHARED_RECURSION_TRACKER);
5811
6035
  }
5812
- if (!this.entitiesToBeDeoptimized.has(UNKNOWN_EXPRESSION)) {
6036
+ if (!this.argumentsToBeDeoptimized.has(UNKNOWN_EXPRESSION)) {
5813
6037
  this.deoptimizationInteractions.push({
5814
6038
  interaction,
5815
6039
  path
@@ -5830,17 +6054,17 @@ class ParameterVariable extends LocalVariable {
5830
6054
  return;
5831
6055
  }
5832
6056
  this.deoptimizedFields.add(key);
5833
- for (const entity of this.entitiesToBeDeoptimized) {
6057
+ for (const entity of this.argumentsToBeDeoptimized) {
5834
6058
  // We do not need a recursion tracker here as we already track whether
5835
6059
  // this field is deoptimized
5836
- entity.deoptimizePath([key]);
6060
+ entity.deoptimizePath([...this.initPath, key]);
5837
6061
  }
5838
6062
  if (key === UnknownKey) {
5839
6063
  // save some memory
5840
6064
  this.deoptimizationInteractions = NO_INTERACTIONS;
5841
6065
  this.deoptimizations = EMPTY_PATH_TRACKER;
5842
6066
  this.deoptimizedFields = UNKNOWN_DEOPTIMIZED_FIELD;
5843
- this.entitiesToBeDeoptimized = UNKNOWN_DEOPTIMIZED_ENTITY;
6067
+ this.argumentsToBeDeoptimized = UNKNOWN_DEOPTIMIZED_ENTITY;
5844
6068
  }
5845
6069
  }
5846
6070
  getReturnExpressionWhenCalledAtPath(path) {
@@ -5855,11 +6079,14 @@ class ParameterVariable extends LocalVariable {
5855
6079
  }
5856
6080
  return UNKNOWN_RETURN_EXPRESSION;
5857
6081
  }
6082
+ includeArgumentPaths(entity, context) {
6083
+ this.includedPathTracker.includeAllPaths(entity, context, this.initPath);
6084
+ }
5858
6085
  }
5859
6086
 
5860
6087
  class ThisVariable extends ParameterVariable {
5861
6088
  constructor(context) {
5862
- super('this', null, context);
6089
+ super('this', null, EMPTY_PATH, context);
5863
6090
  }
5864
6091
  hasEffectsOnInteractionAtPath(path, interaction, context) {
5865
6092
  return (context.replacedVariableInits.get(this) || UNKNOWN_EXPRESSION).hasEffectsOnInteractionAtPath(path, interaction, context);
@@ -5871,7 +6098,7 @@ class CatchBodyScope extends ChildScope {
5871
6098
  super(parent, parent.context);
5872
6099
  this.parent = parent;
5873
6100
  }
5874
- addDeclaration(identifier, context, init, kind) {
6101
+ addDeclaration(identifier, context, init, destructuredInitPath, kind) {
5875
6102
  if (kind === 'var') {
5876
6103
  const name = identifier.name;
5877
6104
  const existingVariable = this.hoistedVariables?.get(name) || this.variables.get(name);
@@ -5884,7 +6111,7 @@ class CatchBodyScope extends ChildScope {
5884
6111
  // the assignment actually goes to the parameter and the var is
5885
6112
  // hoisted without assignment. Locally, it is shadowed by the
5886
6113
  // parameter
5887
- const declaredVariable = this.parent.parent.addDeclaration(identifier, context, UNDEFINED_EXPRESSION, kind);
6114
+ const declaredVariable = this.parent.parent.addDeclaration(identifier, context, UNDEFINED_EXPRESSION, destructuredInitPath, kind);
5888
6115
  // To avoid the need to rewrite the declaration, we link the variable
5889
6116
  // names. If we ever implement a logic that splits initialization and
5890
6117
  // assignment for hoisted vars, the "renderLikeHoisted" logic can be
@@ -5903,7 +6130,7 @@ class CatchBodyScope extends ChildScope {
5903
6130
  return context.error(logRedeclarationError(name), identifier.start);
5904
6131
  }
5905
6132
  // We only add parameters to parameter scopes
5906
- const declaredVariable = this.parent.parent.addDeclaration(identifier, context, init, kind);
6133
+ const declaredVariable = this.parent.parent.addDeclaration(identifier, context, init, destructuredInitPath, kind);
5907
6134
  // Necessary to make sure the init is deoptimized for conditional declarations.
5908
6135
  // We cannot call deoptimizePath here.
5909
6136
  declaredVariable.markInitializersForDeoptimization();
@@ -5911,7 +6138,7 @@ class CatchBodyScope extends ChildScope {
5911
6138
  this.addHoistedVariable(name, declaredVariable);
5912
6139
  return declaredVariable;
5913
6140
  }
5914
- return super.addDeclaration(identifier, context, init, kind);
6141
+ return super.addDeclaration(identifier, context, init, destructuredInitPath, kind);
5915
6142
  }
5916
6143
  }
5917
6144
 
@@ -5921,7 +6148,7 @@ class FunctionBodyScope extends ChildScope {
5921
6148
  }
5922
6149
  // There is stuff that is only allowed in function scopes, i.e. functions can
5923
6150
  // be redeclared, functions and var can redeclare each other
5924
- addDeclaration(identifier, context, init, kind) {
6151
+ addDeclaration(identifier, context, init, destructuredInitPath, kind) {
5925
6152
  const name = identifier.name;
5926
6153
  const existingVariable = this.hoistedVariables?.get(name) || this.variables.get(name);
5927
6154
  if (existingVariable) {
@@ -5933,7 +6160,7 @@ class FunctionBodyScope extends ChildScope {
5933
6160
  }
5934
6161
  context.error(logRedeclarationError(name), identifier.start);
5935
6162
  }
5936
- const newVariable = new LocalVariable(identifier.name, identifier, init, context, kind);
6163
+ const newVariable = new LocalVariable(identifier.name, identifier, init, destructuredInitPath, context, kind);
5937
6164
  this.variables.set(name, newVariable);
5938
6165
  return newVariable;
5939
6166
  }
@@ -5942,21 +6169,21 @@ class FunctionBodyScope extends ChildScope {
5942
6169
  class ParameterScope extends ChildScope {
5943
6170
  constructor(parent, isCatchScope) {
5944
6171
  super(parent, parent.context);
5945
- this.parameters = [];
5946
6172
  this.hasRest = false;
6173
+ this.parameters = [];
5947
6174
  this.bodyScope = isCatchScope ? new CatchBodyScope(this) : new FunctionBodyScope(this);
5948
6175
  }
5949
6176
  /**
5950
6177
  * Adds a parameter to this scope. Parameters must be added in the correct
5951
6178
  * order, i.e. from left to right.
5952
6179
  */
5953
- addParameterDeclaration(identifier) {
6180
+ addParameterDeclaration(identifier, argumentPath) {
5954
6181
  const { name, start } = identifier;
5955
6182
  const existingParameter = this.variables.get(name);
5956
6183
  if (existingParameter) {
5957
6184
  return this.context.error(logDuplicateArgumentNameError(name), start);
5958
6185
  }
5959
- const variable = new ParameterVariable(name, identifier, this.context);
6186
+ const variable = new ParameterVariable(name, identifier, argumentPath, this.context);
5960
6187
  this.variables.set(name, variable);
5961
6188
  // We also add it to the body scope to detect name conflicts with local
5962
6189
  // variables. We still need the intermediate scope, though, as parameter
@@ -5974,42 +6201,56 @@ class ParameterScope extends ChildScope {
5974
6201
  }
5975
6202
  this.hasRest = hasRest;
5976
6203
  }
5977
- includeCallArguments(context, parameters) {
6204
+ includeCallArguments(context, interaction) {
5978
6205
  let calledFromTryStatement = false;
5979
6206
  let argumentIncluded = false;
5980
6207
  const restParameter = this.hasRest && this.parameters[this.parameters.length - 1];
5981
- for (const checkedArgument of parameters) {
5982
- if (checkedArgument instanceof SpreadElement) {
5983
- for (const argument of parameters) {
5984
- argument.include(context, false);
5985
- }
5986
- break;
6208
+ const { args } = interaction;
6209
+ let lastExplicitlyIncludedIndex = args.length - 1;
6210
+ // If there is a SpreadElement, we need to include all arguments after it
6211
+ // because we no longer know which argument corresponds to which parameter.
6212
+ for (let argumentIndex = 1; argumentIndex < args.length; argumentIndex++) {
6213
+ const argument = args[argumentIndex];
6214
+ if (argument instanceof SpreadElement && !argumentIncluded) {
6215
+ argumentIncluded = true;
6216
+ lastExplicitlyIncludedIndex = argumentIndex - 1;
6217
+ }
6218
+ if (argumentIncluded) {
6219
+ argument.includePath(UNKNOWN_PATH, context);
6220
+ argument.include(context, false);
5987
6221
  }
5988
6222
  }
5989
- for (let index = parameters.length - 1; index >= 0; index--) {
5990
- const parameterVariables = this.parameters[index] || restParameter;
5991
- const argument = parameters[index];
6223
+ // Now we go backwards either starting from the last argument or before the
6224
+ // first SpreadElement to ensure all arguments before are included as needed
6225
+ for (let index = lastExplicitlyIncludedIndex; index >= 1; index--) {
6226
+ const parameterVariables = this.parameters[index - 1] || restParameter;
6227
+ const argument = args[index];
5992
6228
  if (parameterVariables) {
5993
6229
  calledFromTryStatement = false;
5994
6230
  if (parameterVariables.length === 0) {
5995
- // handle empty destructuring
6231
+ // handle empty destructuring to avoid destructuring undefined
5996
6232
  argumentIncluded = true;
5997
6233
  }
5998
6234
  else {
5999
6235
  for (const variable of parameterVariables) {
6000
- if (variable.included) {
6001
- argumentIncluded = true;
6002
- }
6003
6236
  if (variable.calledFromTryStatement) {
6004
6237
  calledFromTryStatement = true;
6005
6238
  }
6239
+ if (variable.included) {
6240
+ argumentIncluded = true;
6241
+ if (calledFromTryStatement) {
6242
+ argument.include(context, true);
6243
+ }
6244
+ else {
6245
+ variable.includeArgumentPaths(argument, context);
6246
+ argument.include(context, false);
6247
+ }
6248
+ }
6006
6249
  }
6007
6250
  }
6008
6251
  }
6009
- if (!argumentIncluded && argument.shouldBeIncluded(context)) {
6252
+ if (!argument.included && (argumentIncluded || argument.shouldBeIncluded(context))) {
6010
6253
  argumentIncluded = true;
6011
- }
6012
- if (argumentIncluded) {
6013
6254
  argument.include(context, calledFromTryStatement);
6014
6255
  }
6015
6256
  }
@@ -6025,11 +6266,62 @@ class ReturnValueScope extends ParameterScope {
6025
6266
  addReturnExpression(expression) {
6026
6267
  this.returnExpressions.push(expression);
6027
6268
  }
6269
+ deoptimizeArgumentsOnCall(interaction) {
6270
+ const { parameters } = this;
6271
+ const { args } = interaction;
6272
+ let position = 0;
6273
+ for (; position < args.length - 1; position++) {
6274
+ // Only the "this" argument arg[0] can be null
6275
+ const argument = args[position + 1];
6276
+ if (argument instanceof SpreadElement) {
6277
+ // This deoptimizes the current and remaining parameters and arguments
6278
+ for (; position < parameters.length; position++) {
6279
+ args[position + 1]?.deoptimizePath(UNKNOWN_PATH);
6280
+ parameters[position].forEach(variable => variable.markReassigned());
6281
+ }
6282
+ break;
6283
+ }
6284
+ if (this.hasRest && position >= parameters.length - 1) {
6285
+ argument.deoptimizePath(UNKNOWN_PATH);
6286
+ }
6287
+ else {
6288
+ const variables = parameters[position];
6289
+ if (variables) {
6290
+ for (const variable of variables) {
6291
+ variable.addArgumentValue(argument);
6292
+ }
6293
+ }
6294
+ this.addArgumentToBeDeoptimized(argument);
6295
+ }
6296
+ }
6297
+ const nonRestParameterLength = this.hasRest ? parameters.length - 1 : parameters.length;
6298
+ for (; position < nonRestParameterLength; position++) {
6299
+ for (const variable of parameters[position]) {
6300
+ variable.addArgumentValue(UNDEFINED_EXPRESSION);
6301
+ }
6302
+ }
6303
+ }
6028
6304
  getReturnExpression() {
6029
6305
  if (this.returnExpression === null)
6030
6306
  this.updateReturnExpression();
6031
6307
  return this.returnExpression;
6032
6308
  }
6309
+ deoptimizeAllParameters() {
6310
+ for (const parameter of this.parameters) {
6311
+ for (const variable of parameter) {
6312
+ variable.deoptimizePath(UNKNOWN_PATH);
6313
+ variable.markReassigned();
6314
+ }
6315
+ }
6316
+ }
6317
+ reassignAllParameters() {
6318
+ for (const parameter of this.parameters) {
6319
+ for (const variable of parameter) {
6320
+ variable.markReassigned();
6321
+ }
6322
+ }
6323
+ }
6324
+ addArgumentToBeDeoptimized(_argument) { }
6033
6325
  updateReturnExpression() {
6034
6326
  if (this.returnExpressions.length === 1) {
6035
6327
  this.returnExpression = this.returnExpressions[0];
@@ -6045,24 +6337,30 @@ class ReturnValueScope extends ParameterScope {
6045
6337
 
6046
6338
  class FunctionScope extends ReturnValueScope {
6047
6339
  constructor(parent) {
6048
- const { context } = parent;
6049
6340
  super(parent, false);
6341
+ const { context } = parent;
6050
6342
  this.variables.set('arguments', (this.argumentsVariable = new ArgumentsVariable(context)));
6051
6343
  this.variables.set('this', (this.thisVariable = new ThisVariable(context)));
6052
6344
  }
6053
6345
  findLexicalBoundary() {
6054
6346
  return this;
6055
6347
  }
6056
- includeCallArguments(context, parameters) {
6057
- super.includeCallArguments(context, parameters);
6348
+ includeCallArguments(context, interaction) {
6349
+ super.includeCallArguments(context, interaction);
6058
6350
  if (this.argumentsVariable.included) {
6059
- for (const argument of parameters) {
6060
- if (!argument.included) {
6351
+ const { args } = interaction;
6352
+ for (let argumentIndex = 1; argumentIndex < args.length; argumentIndex++) {
6353
+ const argument = args[argumentIndex];
6354
+ if (argument) {
6355
+ argument.includePath(UNKNOWN_PATH, context);
6061
6356
  argument.include(context, false);
6062
6357
  }
6063
6358
  }
6064
6359
  }
6065
6360
  }
6361
+ addArgumentToBeDeoptimized(argument) {
6362
+ this.argumentsVariable.addArgumentToBeDeoptimized(argument);
6363
+ }
6066
6364
  }
6067
6365
 
6068
6366
  class ExpressionStatement extends NodeBase {
@@ -6090,8 +6388,9 @@ class ExpressionStatement extends NodeBase {
6090
6388
  return this.parent.type !== Program$1;
6091
6389
  return super.shouldBeIncluded(context);
6092
6390
  }
6093
- applyDeoptimizations() { }
6094
6391
  }
6392
+ ExpressionStatement.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
6393
+ ExpressionStatement.prototype.applyDeoptimizations = doNotDeoptimize;
6095
6394
 
6096
6395
  class BlockStatement extends NodeBase {
6097
6396
  get deoptimizeBody() {
@@ -6156,6 +6455,8 @@ class BlockStatement extends NodeBase {
6156
6455
  }
6157
6456
  }
6158
6457
  }
6458
+ BlockStatement.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
6459
+ BlockStatement.prototype.applyDeoptimizations = doNotDeoptimize;
6159
6460
 
6160
6461
  class RestElement extends NodeBase {
6161
6462
  constructor() {
@@ -6165,9 +6466,12 @@ class RestElement extends NodeBase {
6165
6466
  addExportedVariables(variables, exportNamesByVariable) {
6166
6467
  this.argument.addExportedVariables(variables, exportNamesByVariable);
6167
6468
  }
6168
- declare(kind, init) {
6469
+ declare(kind, destructuredInitPath, init) {
6169
6470
  this.declarationInit = init;
6170
- return this.argument.declare(kind, UNKNOWN_EXPRESSION);
6471
+ return this.argument.declare(kind, getIncludedPatternPath$1(destructuredInitPath), init);
6472
+ }
6473
+ deoptimizeAssignment(destructuredInitPath, init) {
6474
+ this.argument.deoptimizeAssignment(getIncludedPatternPath$1(destructuredInitPath), init);
6171
6475
  }
6172
6476
  deoptimizePath(path) {
6173
6477
  if (path.length === 0) {
@@ -6178,6 +6482,20 @@ class RestElement extends NodeBase {
6178
6482
  return (path.length > 0 ||
6179
6483
  this.argument.hasEffectsOnInteractionAtPath(EMPTY_PATH, interaction, context));
6180
6484
  }
6485
+ hasEffectsWhenDestructuring(context, destructuredInitPath, init) {
6486
+ return this.argument.hasEffectsWhenDestructuring(context, getIncludedPatternPath$1(destructuredInitPath), init);
6487
+ }
6488
+ includeDestructuredIfNecessary(context, destructuredInitPath, init) {
6489
+ return (this.included =
6490
+ this.argument.includeDestructuredIfNecessary(context, getIncludedPatternPath$1(destructuredInitPath), init) || this.included);
6491
+ }
6492
+ include(context, includeChildrenRecursively) {
6493
+ if (!this.included)
6494
+ this.includeNode(context);
6495
+ // This should just include the identifier, its properties should be
6496
+ // included where the variable is used.
6497
+ this.argument.include(context, includeChildrenRecursively);
6498
+ }
6181
6499
  markDeclarationReached() {
6182
6500
  this.argument.markDeclarationReached();
6183
6501
  }
@@ -6189,12 +6507,16 @@ class RestElement extends NodeBase {
6189
6507
  }
6190
6508
  }
6191
6509
  }
6510
+ RestElement.prototype.includeNode = onlyIncludeSelf;
6511
+ const getIncludedPatternPath$1 = (destructuredInitPath) => destructuredInitPath.at(-1) === UnknownKey
6512
+ ? destructuredInitPath
6513
+ : [...destructuredInitPath, UnknownKey];
6192
6514
 
6193
6515
  class FunctionBase extends NodeBase {
6194
6516
  constructor() {
6195
6517
  super(...arguments);
6196
- this.objectEntity = null;
6197
6518
  this.parameterVariableValuesDeoptimized = false;
6519
+ this.includeCallArguments = this.scope.includeCallArguments.bind(this.scope);
6198
6520
  }
6199
6521
  get async() {
6200
6522
  return isFlagSet(this.flags, 256 /* Flag.async */);
@@ -6214,53 +6536,9 @@ class FunctionBase extends NodeBase {
6214
6536
  set generator(value) {
6215
6537
  this.flags = setFlag(this.flags, 4194304 /* Flag.generator */, value);
6216
6538
  }
6217
- updateParameterVariableValues(_arguments) {
6218
- for (let position = 0; position < this.params.length; position++) {
6219
- const parameter = this.params[position];
6220
- if (!(parameter instanceof Identifier)) {
6221
- continue;
6222
- }
6223
- const parameterVariable = parameter.variable;
6224
- const argument = _arguments[position + 1] ?? UNDEFINED_EXPRESSION;
6225
- parameterVariable.updateKnownValue(argument);
6226
- }
6227
- }
6228
- deoptimizeParameterVariableValues() {
6229
- for (const parameter of this.params) {
6230
- if (parameter instanceof Identifier) {
6231
- const parameterVariable = parameter.variable;
6232
- parameterVariable.markReassigned();
6233
- }
6234
- }
6235
- }
6236
6539
  deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
6237
- if (interaction.type === INTERACTION_CALLED) {
6238
- const { parameters } = this.scope;
6239
- const { args } = interaction;
6240
- let hasRest = false;
6241
- for (let position = 0; position < args.length - 1; position++) {
6242
- const parameter = this.params[position];
6243
- // Only the "this" argument arg[0] can be null
6244
- const argument = args[position + 1];
6245
- if (argument instanceof SpreadElement) {
6246
- this.deoptimizeParameterVariableValues();
6247
- }
6248
- if (hasRest || parameter instanceof RestElement) {
6249
- hasRest = true;
6250
- argument.deoptimizePath(UNKNOWN_PATH);
6251
- }
6252
- else if (parameter instanceof Identifier) {
6253
- parameters[position][0].addEntityToBeDeoptimized(argument);
6254
- this.addArgumentToBeDeoptimized(argument);
6255
- }
6256
- else if (parameter) {
6257
- argument.deoptimizePath(UNKNOWN_PATH);
6258
- }
6259
- else {
6260
- this.addArgumentToBeDeoptimized(argument);
6261
- }
6262
- }
6263
- this.updateParameterVariableValues(args);
6540
+ if (interaction.type === INTERACTION_CALLED && path.length === 0) {
6541
+ this.scope.deoptimizeArgumentsOnCall(interaction);
6264
6542
  }
6265
6543
  else {
6266
6544
  this.getObjectEntity().deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker);
@@ -6272,12 +6550,7 @@ class FunctionBase extends NodeBase {
6272
6550
  // A reassignment of UNKNOWN_PATH is considered equivalent to having lost track
6273
6551
  // which means the return expression and parameters need to be reassigned
6274
6552
  this.scope.getReturnExpression().deoptimizePath(UNKNOWN_PATH);
6275
- for (const parameterList of this.scope.parameters) {
6276
- for (const parameter of parameterList) {
6277
- parameter.deoptimizePath(UNKNOWN_PATH);
6278
- parameter.markReassigned();
6279
- }
6280
- }
6553
+ this.scope.deoptimizeAllParameters();
6281
6554
  }
6282
6555
  }
6283
6556
  getLiteralValueAtPath(path, recursionTracker, origin) {
@@ -6315,8 +6588,13 @@ class FunctionBase extends NodeBase {
6315
6588
  return true;
6316
6589
  }
6317
6590
  }
6318
- for (const parameter of this.params) {
6319
- if (parameter.hasEffects(context))
6591
+ const { propertyReadSideEffects } = this.scope.context.options
6592
+ .treeshake;
6593
+ for (let index = 0; index < this.params.length; index++) {
6594
+ const parameter = this.params[index];
6595
+ if (parameter.hasEffects(context) ||
6596
+ (propertyReadSideEffects &&
6597
+ parameter.hasEffectsWhenDestructuring(context, EMPTY_PATH, interaction.args[index + 1] || UNDEFINED_EXPRESSION)))
6320
6598
  return true;
6321
6599
  }
6322
6600
  return false;
@@ -6335,21 +6613,17 @@ class FunctionBase extends NodeBase {
6335
6613
  return variable?.getOnlyFunctionCallUsed() ?? false;
6336
6614
  }
6337
6615
  include(context, includeChildrenRecursively) {
6338
- if (!this.parameterVariableValuesDeoptimized && !this.onlyFunctionCallUsed()) {
6616
+ if (!this.included)
6617
+ this.includeNode(context);
6618
+ if (!(this.parameterVariableValuesDeoptimized || this.onlyFunctionCallUsed())) {
6339
6619
  this.parameterVariableValuesDeoptimized = true;
6340
- this.deoptimizeParameterVariableValues();
6620
+ this.scope.reassignAllParameters();
6341
6621
  }
6342
- if (!this.deoptimized)
6343
- this.applyDeoptimizations();
6344
- this.included = true;
6345
6622
  const { brokenFlow } = context;
6346
6623
  context.brokenFlow = false;
6347
6624
  this.body.include(context, includeChildrenRecursively);
6348
6625
  context.brokenFlow = brokenFlow;
6349
6626
  }
6350
- includeCallArguments(context, parameters) {
6351
- this.scope.includeCallArguments(context, parameters);
6352
- }
6353
6627
  initialise() {
6354
6628
  super.initialise();
6355
6629
  if (this.body instanceof BlockStatement) {
@@ -6371,14 +6645,14 @@ class FunctionBase extends NodeBase {
6371
6645
  // so that the scope already knows all parameters and can detect conflicts
6372
6646
  // when parsing the body.
6373
6647
  const parameters = (this.params = params.map((parameter) => new (context.getNodeConstructor(parameter.type))(this, scope).parseNode(parameter)));
6374
- scope.addParameterVariables(parameters.map(parameter => parameter.declare('parameter', UNKNOWN_EXPRESSION)), parameters[parameters.length - 1] instanceof RestElement);
6648
+ scope.addParameterVariables(parameters.map(parameter => parameter.declare('parameter', EMPTY_PATH, UNKNOWN_EXPRESSION)), parameters[parameters.length - 1] instanceof RestElement);
6375
6649
  this.body = new (context.getNodeConstructor(body.type))(this, bodyScope).parseNode(body);
6376
6650
  return super.parseNode(esTreeNode);
6377
6651
  }
6378
- addArgumentToBeDeoptimized(_argument) { }
6379
- applyDeoptimizations() { }
6380
6652
  }
6381
6653
  FunctionBase.prototype.preventChildBlockScope = true;
6654
+ FunctionBase.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
6655
+ FunctionBase.prototype.applyDeoptimizations = doNotDeoptimize;
6382
6656
 
6383
6657
  class FunctionNode extends FunctionBase {
6384
6658
  constructor() {
@@ -6390,18 +6664,16 @@ class FunctionNode extends FunctionBase {
6390
6664
  this.constructedEntity = new ObjectEntity(Object.create(null), OBJECT_PROTOTYPE);
6391
6665
  // This makes sure that all deoptimizations of "this" are applied to the
6392
6666
  // constructed entity.
6393
- this.scope.thisVariable.addEntityToBeDeoptimized(this.constructedEntity);
6667
+ this.scope.thisVariable.addArgumentValue(this.constructedEntity);
6394
6668
  }
6395
6669
  deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
6396
6670
  super.deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker);
6397
6671
  if (interaction.type === INTERACTION_CALLED && path.length === 0 && interaction.args[0]) {
6398
6672
  // args[0] is the "this" argument
6399
- this.scope.thisVariable.addEntityToBeDeoptimized(interaction.args[0]);
6673
+ this.scope.thisVariable.addArgumentValue(interaction.args[0]);
6400
6674
  }
6401
6675
  }
6402
6676
  hasEffects(context) {
6403
- if (!this.deoptimized)
6404
- this.applyDeoptimizations();
6405
6677
  if (this.annotationNoSideEffects) {
6406
6678
  return false;
6407
6679
  }
@@ -6439,7 +6711,7 @@ class FunctionNode extends FunctionBase {
6439
6711
  }
6440
6712
  include(context, includeChildrenRecursively) {
6441
6713
  super.include(context, includeChildrenRecursively);
6442
- this.id?.include();
6714
+ this.id?.include(context);
6443
6715
  const hasArguments = this.scope.argumentsVariable.included;
6444
6716
  for (const parameter of this.params) {
6445
6717
  if (!(parameter instanceof Identifier) || hasArguments) {
@@ -6447,12 +6719,18 @@ class FunctionNode extends FunctionBase {
6447
6719
  }
6448
6720
  }
6449
6721
  }
6722
+ includeNode(context) {
6723
+ this.included = true;
6724
+ const hasArguments = this.scope.argumentsVariable.included;
6725
+ for (const parameter of this.params) {
6726
+ if (!(parameter instanceof Identifier) || hasArguments) {
6727
+ parameter.includePath(UNKNOWN_PATH, context);
6728
+ }
6729
+ }
6730
+ }
6450
6731
  initialise() {
6451
6732
  super.initialise();
6452
- this.id?.declare('function', this);
6453
- }
6454
- addArgumentToBeDeoptimized(argument) {
6455
- this.scope.argumentsVariable.addArgumentToBeDeoptimized(argument);
6733
+ this.id?.declare('function', EMPTY_PATH, this);
6456
6734
  }
6457
6735
  getObjectEntity() {
6458
6736
  if (this.objectEntity !== null) {
@@ -6502,11 +6780,16 @@ function getFunctionIdInsertPosition(code, start) {
6502
6780
  }
6503
6781
  class ExportDefaultDeclaration extends NodeBase {
6504
6782
  include(context, includeChildrenRecursively) {
6505
- super.include(context, includeChildrenRecursively);
6783
+ this.included = true;
6784
+ this.declaration.include(context, includeChildrenRecursively);
6506
6785
  if (includeChildrenRecursively) {
6507
- this.scope.context.includeVariableInModule(this.variable);
6786
+ this.scope.context.includeVariableInModule(this.variable, UNKNOWN_PATH, context);
6508
6787
  }
6509
6788
  }
6789
+ includePath(path, context) {
6790
+ this.included = true;
6791
+ this.declaration.includePath(path, context);
6792
+ }
6510
6793
  initialise() {
6511
6794
  super.initialise();
6512
6795
  const declaration = this.declaration;
@@ -6551,7 +6834,6 @@ class ExportDefaultDeclaration extends NodeBase {
6551
6834
  }
6552
6835
  this.declaration.render(code, options);
6553
6836
  }
6554
- applyDeoptimizations() { }
6555
6837
  renderNamedDeclaration(code, declarationStart, idInsertPosition, options) {
6556
6838
  const { exportNamesByVariable, format, snippets: { getPropertyAccess } } = options;
6557
6839
  const name = this.variable.getName(getPropertyAccess);
@@ -6582,6 +6864,8 @@ class ExportDefaultDeclaration extends NodeBase {
6582
6864
  }
6583
6865
  }
6584
6866
  ExportDefaultDeclaration.prototype.needsBoundaries = true;
6867
+ ExportDefaultDeclaration.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
6868
+ ExportDefaultDeclaration.prototype.applyDeoptimizations = doNotDeoptimize;
6585
6869
 
6586
6870
  const needsEscapeRegEx = /[\n\r'\\\u2028\u2029]/;
6587
6871
  const quoteNewlineRegEx = /([\n\r'\u2028\u2029])/g;
@@ -6851,6 +7135,7 @@ class Literal extends NodeBase {
6851
7135
  }
6852
7136
  }
6853
7137
  }
7138
+ Literal.prototype.includeNode = onlyIncludeSelf;
6854
7139
 
6855
7140
  function getChainElementLiteralValueAtPath(element, object, path, recursionTracker, origin) {
6856
7141
  if ('getLiteralValueAtPathAsChainElement' in object) {
@@ -6866,8 +7151,6 @@ function getChainElementLiteralValueAtPath(element, object, path, recursionTrack
6866
7151
  return element.getLiteralValueAtPath(path, recursionTracker, origin);
6867
7152
  }
6868
7153
 
6869
- // To avoid infinite recursions
6870
- const MAX_PATH_DEPTH = 7;
6871
7154
  function getResolvablePropertyKey(memberExpression) {
6872
7155
  return memberExpression.computed
6873
7156
  ? getResolvableComputedPropertyKey(memberExpression.property)
@@ -6966,18 +7249,27 @@ class MemberExpression extends NodeBase {
6966
7249
  }
6967
7250
  else if (!this.isUndefined) {
6968
7251
  if (path.length < MAX_PATH_DEPTH) {
6969
- this.object.deoptimizeArgumentsOnInteractionAtPath(interaction, [this.getPropertyKey(), ...path], recursionTracker);
7252
+ this.object.deoptimizeArgumentsOnInteractionAtPath(interaction, this.propertyKey === UnknownKey ? UNKNOWN_PATH : [this.propertyKey, ...path], recursionTracker);
6970
7253
  }
6971
7254
  else {
6972
7255
  deoptimizeInteraction(interaction);
6973
7256
  }
6974
7257
  }
6975
7258
  }
7259
+ deoptimizeAssignment(destructuredInitPath, init) {
7260
+ this.deoptimizePath(EMPTY_PATH);
7261
+ init.deoptimizePath([...destructuredInitPath, UnknownKey]);
7262
+ }
6976
7263
  deoptimizeCache() {
7264
+ if (this.propertyKey === this.dynamicPropertyKey)
7265
+ return;
6977
7266
  const { expressionsToBeDeoptimized, object } = this;
6978
7267
  this.expressionsToBeDeoptimized = EMPTY_ARRAY;
6979
- this.propertyKey = UnknownKey;
7268
+ this.dynamicPropertyKey = this.propertyKey;
6980
7269
  object.deoptimizePath(UNKNOWN_PATH);
7270
+ if (this.included) {
7271
+ object.includePath(UNKNOWN_PATH, createInclusionContext());
7272
+ }
6981
7273
  for (const expression of expressionsToBeDeoptimized) {
6982
7274
  expression.deoptimizeCache();
6983
7275
  }
@@ -6988,11 +7280,13 @@ class MemberExpression extends NodeBase {
6988
7280
  if (this.variable) {
6989
7281
  this.variable.deoptimizePath(path);
6990
7282
  }
6991
- else if (!this.isUndefined && path.length < MAX_PATH_DEPTH) {
6992
- const propertyKey = this.getPropertyKey();
7283
+ else if (!this.isUndefined) {
7284
+ const { propertyKey } = this;
6993
7285
  this.object.deoptimizePath([
6994
7286
  propertyKey === UnknownKey ? UnknownNonAccessorKey : propertyKey,
6995
- ...path
7287
+ ...(path.length < MAX_PATH_DEPTH
7288
+ ? path
7289
+ : [...path.slice(0, MAX_PATH_DEPTH), UnknownKey])
6996
7290
  ]);
6997
7291
  }
6998
7292
  }
@@ -7003,9 +7297,11 @@ class MemberExpression extends NodeBase {
7003
7297
  if (this.isUndefined) {
7004
7298
  return undefined;
7005
7299
  }
7006
- if (this.propertyKey !== UnknownKey && path.length < MAX_PATH_DEPTH) {
7007
- this.expressionsToBeDeoptimized.push(origin);
7008
- return this.object.getLiteralValueAtPath([this.getPropertyKey(), ...path], recursionTracker, origin);
7300
+ const propertyKey = this.getDynamicPropertyKey();
7301
+ if (propertyKey !== UnknownKey && path.length < MAX_PATH_DEPTH) {
7302
+ if (propertyKey !== this.propertyKey)
7303
+ this.expressionsToBeDeoptimized.push(origin);
7304
+ return this.object.getLiteralValueAtPath([propertyKey, ...path], recursionTracker, origin);
7009
7305
  }
7010
7306
  return UnknownValue;
7011
7307
  }
@@ -7025,9 +7321,11 @@ class MemberExpression extends NodeBase {
7025
7321
  if (this.isUndefined) {
7026
7322
  return [UNDEFINED_EXPRESSION, false];
7027
7323
  }
7028
- if (this.propertyKey !== UnknownKey && path.length < MAX_PATH_DEPTH) {
7029
- this.expressionsToBeDeoptimized.push(origin);
7030
- return this.object.getReturnExpressionWhenCalledAtPath([this.getPropertyKey(), ...path], interaction, recursionTracker, origin);
7324
+ const propertyKey = this.getDynamicPropertyKey();
7325
+ if (propertyKey !== UnknownKey && path.length < MAX_PATH_DEPTH) {
7326
+ if (propertyKey !== this.propertyKey)
7327
+ this.expressionsToBeDeoptimized.push(origin);
7328
+ return this.object.getReturnExpressionWhenCalledAtPath([propertyKey, ...path], interaction, recursionTracker, origin);
7031
7329
  }
7032
7330
  return UNKNOWN_RETURN_EXPRESSION;
7033
7331
  }
@@ -7073,14 +7371,45 @@ class MemberExpression extends NodeBase {
7073
7371
  return true;
7074
7372
  }
7075
7373
  if (path.length < MAX_PATH_DEPTH) {
7076
- return this.object.hasEffectsOnInteractionAtPath([this.getPropertyKey(), ...path], interaction, context);
7374
+ return this.object.hasEffectsOnInteractionAtPath([this.getDynamicPropertyKey(), ...path], interaction, context);
7077
7375
  }
7078
7376
  return true;
7079
7377
  }
7378
+ hasEffectsWhenDestructuring(context, destructuredInitPath, init) {
7379
+ return (destructuredInitPath.length > 0 &&
7380
+ init.hasEffectsOnInteractionAtPath(destructuredInitPath, NODE_INTERACTION_UNKNOWN_ACCESS, context));
7381
+ }
7080
7382
  include(context, includeChildrenRecursively) {
7383
+ if (!this.included)
7384
+ this.includeNode(context);
7385
+ this.object.include(context, includeChildrenRecursively);
7386
+ this.property.include(context, includeChildrenRecursively);
7387
+ }
7388
+ includeNode(context) {
7389
+ this.included = true;
7081
7390
  if (!this.deoptimized)
7082
7391
  this.applyDeoptimizations();
7083
- this.includeProperties(context, includeChildrenRecursively);
7392
+ if (this.variable) {
7393
+ this.scope.context.includeVariableInModule(this.variable, EMPTY_PATH, context);
7394
+ }
7395
+ else if (!this.isUndefined) {
7396
+ this.object.includePath([this.propertyKey], context);
7397
+ }
7398
+ }
7399
+ includePath(path, context) {
7400
+ if (!this.included)
7401
+ this.includeNode(context);
7402
+ if (this.variable) {
7403
+ this.variable?.includePath(path, context);
7404
+ }
7405
+ else if (!this.isUndefined) {
7406
+ this.object.includePath([
7407
+ this.propertyKey,
7408
+ ...(path.length < MAX_PATH_DEPTH
7409
+ ? path
7410
+ : [...path.slice(0, MAX_PATH_DEPTH), UnknownKey])
7411
+ ], context);
7412
+ }
7084
7413
  }
7085
7414
  includeAsAssignmentTarget(context, includeChildrenRecursively, deoptimizeAccess) {
7086
7415
  if (!this.assignmentDeoptimized)
@@ -7089,20 +7418,34 @@ class MemberExpression extends NodeBase {
7089
7418
  this.include(context, includeChildrenRecursively);
7090
7419
  }
7091
7420
  else {
7092
- this.includeProperties(context, includeChildrenRecursively);
7421
+ if (!this.included)
7422
+ this.includeNode(context);
7423
+ this.object.include(context, includeChildrenRecursively);
7424
+ this.property.include(context, includeChildrenRecursively);
7093
7425
  }
7094
7426
  }
7095
- includeCallArguments(context, parameters) {
7427
+ includeCallArguments(context, interaction) {
7096
7428
  if (this.variable) {
7097
- this.variable.includeCallArguments(context, parameters);
7429
+ this.variable.includeCallArguments(context, interaction);
7098
7430
  }
7099
7431
  else {
7100
- super.includeCallArguments(context, parameters);
7432
+ super.includeCallArguments(context, interaction);
7433
+ }
7434
+ }
7435
+ includeDestructuredIfNecessary(context, destructuredInitPath, init) {
7436
+ if ((this.included ||=
7437
+ destructuredInitPath.length > 0 &&
7438
+ !context.brokenFlow &&
7439
+ init.hasEffectsOnInteractionAtPath(destructuredInitPath, NODE_INTERACTION_UNKNOWN_ACCESS, createHasEffectsContext()))) {
7440
+ init.include(context, false);
7441
+ return true;
7101
7442
  }
7443
+ return false;
7102
7444
  }
7103
7445
  initialise() {
7104
7446
  super.initialise();
7105
- this.propertyKey = getResolvablePropertyKey(this);
7447
+ this.dynamicPropertyKey = getResolvablePropertyKey(this);
7448
+ this.propertyKey = this.dynamicPropertyKey === null ? UnknownKey : this.dynamicPropertyKey;
7106
7449
  this.accessInteraction = { args: [this.object], type: INTERACTION_ACCESSED };
7107
7450
  }
7108
7451
  render(code, options, { renderedParentType, isCalleeOfRenderedParent, renderedSurroundingElement } = BLANK) {
@@ -7139,8 +7482,7 @@ class MemberExpression extends NodeBase {
7139
7482
  this.bound &&
7140
7483
  propertyReadSideEffects &&
7141
7484
  !(this.variable || this.isUndefined)) {
7142
- const propertyKey = this.getPropertyKey();
7143
- this.object.deoptimizeArgumentsOnInteractionAtPath(this.accessInteraction, [propertyKey], SHARED_RECURSION_TRACKER);
7485
+ this.object.deoptimizeArgumentsOnInteractionAtPath(this.accessInteraction, [this.propertyKey], SHARED_RECURSION_TRACKER);
7144
7486
  this.scope.context.requestTreeshakingPass();
7145
7487
  }
7146
7488
  if (this.variable) {
@@ -7157,7 +7499,7 @@ class MemberExpression extends NodeBase {
7157
7499
  this.bound &&
7158
7500
  propertyReadSideEffects &&
7159
7501
  !(this.variable || this.isUndefined)) {
7160
- this.object.deoptimizeArgumentsOnInteractionAtPath(this.assignmentInteraction, [this.getPropertyKey()], SHARED_RECURSION_TRACKER);
7502
+ this.object.deoptimizeArgumentsOnInteractionAtPath(this.assignmentInteraction, [this.propertyKey], SHARED_RECURSION_TRACKER);
7161
7503
  this.scope.context.requestTreeshakingPass();
7162
7504
  }
7163
7505
  }
@@ -7166,24 +7508,24 @@ class MemberExpression extends NodeBase {
7166
7508
  const variable = this.scope.findVariable(this.object.name);
7167
7509
  if (variable.isNamespace) {
7168
7510
  if (this.variable) {
7169
- this.scope.context.includeVariableInModule(this.variable);
7511
+ this.scope.context.includeVariableInModule(this.variable, UNKNOWN_PATH, createInclusionContext());
7170
7512
  }
7171
7513
  this.scope.context.log(LOGLEVEL_WARN, logIllegalImportReassignment(this.object.name, this.scope.context.module.id), this.start);
7172
7514
  }
7173
7515
  }
7174
7516
  }
7175
- getPropertyKey() {
7176
- if (this.propertyKey === null) {
7177
- this.propertyKey = UnknownKey;
7517
+ getDynamicPropertyKey() {
7518
+ if (this.dynamicPropertyKey === null) {
7519
+ this.dynamicPropertyKey = this.propertyKey;
7178
7520
  const value = this.property.getLiteralValueAtPath(EMPTY_PATH, SHARED_RECURSION_TRACKER, this);
7179
- return (this.propertyKey =
7521
+ return (this.dynamicPropertyKey =
7180
7522
  value === SymbolToStringTag
7181
7523
  ? value
7182
7524
  : typeof value === 'symbol'
7183
7525
  ? UnknownKey
7184
7526
  : String(value));
7185
7527
  }
7186
- return this.propertyKey;
7528
+ return this.dynamicPropertyKey;
7187
7529
  }
7188
7530
  hasAccessEffect(context) {
7189
7531
  const { propertyReadSideEffects } = this.scope.context.options
@@ -7191,17 +7533,7 @@ class MemberExpression extends NodeBase {
7191
7533
  return (!(this.variable || this.isUndefined) &&
7192
7534
  propertyReadSideEffects &&
7193
7535
  (propertyReadSideEffects === 'always' ||
7194
- this.object.hasEffectsOnInteractionAtPath([this.getPropertyKey()], this.accessInteraction, context)));
7195
- }
7196
- includeProperties(context, includeChildrenRecursively) {
7197
- if (!this.included) {
7198
- this.included = true;
7199
- if (this.variable) {
7200
- this.scope.context.includeVariableInModule(this.variable);
7201
- }
7202
- }
7203
- this.object.include(context, includeChildrenRecursively);
7204
- this.property.include(context, includeChildrenRecursively);
7536
+ this.object.hasEffectsOnInteractionAtPath([this.getDynamicPropertyKey()], this.accessInteraction, context)));
7205
7537
  }
7206
7538
  }
7207
7539
  function resolveNamespaceVariables(baseVariable, path, astContext) {
@@ -7245,18 +7577,20 @@ class MetaProperty extends NodeBase {
7245
7577
  return path.length > 1 || type !== INTERACTION_ACCESSED;
7246
7578
  }
7247
7579
  include() {
7248
- if (!this.included) {
7249
- this.included = true;
7250
- if (this.meta.name === IMPORT) {
7251
- this.scope.context.addImportMeta(this);
7252
- const parent = this.parent;
7253
- const metaProperty = (this.metaProperty =
7254
- parent instanceof MemberExpression && typeof parent.propertyKey === 'string'
7255
- ? parent.propertyKey
7256
- : null);
7257
- if (metaProperty?.startsWith(FILE_PREFIX)) {
7258
- this.referenceId = metaProperty.slice(FILE_PREFIX.length);
7259
- }
7580
+ if (!this.included)
7581
+ this.includeNode();
7582
+ }
7583
+ includeNode() {
7584
+ this.included = true;
7585
+ if (this.meta.name === IMPORT) {
7586
+ this.scope.context.addImportMeta(this);
7587
+ const parent = this.parent;
7588
+ const metaProperty = (this.metaProperty =
7589
+ parent instanceof MemberExpression && typeof parent.propertyKey === 'string'
7590
+ ? parent.propertyKey
7591
+ : null);
7592
+ if (metaProperty?.startsWith(FILE_PREFIX)) {
7593
+ this.referenceId = metaProperty.slice(FILE_PREFIX.length);
7260
7594
  }
7261
7595
  }
7262
7596
  }
@@ -7363,7 +7697,7 @@ class UndefinedVariable extends Variable {
7363
7697
 
7364
7698
  class ExportDefaultVariable extends LocalVariable {
7365
7699
  constructor(name, exportDefaultDeclaration, context) {
7366
- super(name, exportDefaultDeclaration, exportDefaultDeclaration.declaration, context, 'other');
7700
+ super(name, exportDefaultDeclaration, exportDefaultDeclaration.declaration, EMPTY_PATH, context, 'other');
7367
7701
  this.hasId = false;
7368
7702
  this.originalId = null;
7369
7703
  this.originalVariable = null;
@@ -7512,8 +7846,8 @@ class NamespaceVariable extends Variable {
7512
7846
  return (!memberVariable ||
7513
7847
  memberVariable.hasEffectsOnInteractionAtPath(path.slice(1), interaction, context));
7514
7848
  }
7515
- include() {
7516
- super.include();
7849
+ includePath(path, context) {
7850
+ super.includePath(path, context);
7517
7851
  this.context.includeAllExports();
7518
7852
  }
7519
7853
  prepare(accessedGlobalsByScope) {
@@ -7606,9 +7940,9 @@ class SyntheticNamedExportVariable extends Variable {
7606
7940
  getName(getPropertyAccess) {
7607
7941
  return `${this.syntheticNamespace.getName(getPropertyAccess)}${getPropertyAccess(this.name)}`;
7608
7942
  }
7609
- include() {
7610
- super.include();
7611
- this.context.includeVariableInModule(this.syntheticNamespace);
7943
+ includePath(path, context) {
7944
+ super.includePath(path, context);
7945
+ this.context.includeVariableInModule(this.syntheticNamespace, path, context);
7612
7946
  }
7613
7947
  setRenderNames(baseName, name) {
7614
7948
  super.setRenderNames(baseName, name);
@@ -10813,21 +11147,37 @@ class ArrayPattern extends NodeBase {
10813
11147
  element?.addExportedVariables(variables, exportNamesByVariable);
10814
11148
  }
10815
11149
  }
10816
- declare(kind) {
11150
+ declare(kind, destructuredInitPath, init) {
10817
11151
  const variables = [];
11152
+ const includedPatternPath = getIncludedPatternPath(destructuredInitPath);
10818
11153
  for (const element of this.elements) {
10819
11154
  if (element !== null) {
10820
- variables.push(...element.declare(kind, UNKNOWN_EXPRESSION));
11155
+ variables.push(...element.declare(kind, includedPatternPath, init));
10821
11156
  }
10822
11157
  }
10823
11158
  return variables;
10824
11159
  }
11160
+ deoptimizeAssignment(destructuredInitPath, init) {
11161
+ const includedPatternPath = getIncludedPatternPath(destructuredInitPath);
11162
+ for (const element of this.elements) {
11163
+ element?.deoptimizeAssignment(includedPatternPath, init);
11164
+ }
11165
+ }
10825
11166
  // Patterns can only be deoptimized at the empty path at the moment
10826
11167
  deoptimizePath() {
10827
11168
  for (const element of this.elements) {
10828
11169
  element?.deoptimizePath(EMPTY_PATH);
10829
11170
  }
10830
11171
  }
11172
+ hasEffectsWhenDestructuring(context, destructuredInitPath, init) {
11173
+ const includedPatternPath = getIncludedPatternPath(destructuredInitPath);
11174
+ for (const element of this.elements) {
11175
+ if (element?.hasEffectsWhenDestructuring(context, includedPatternPath, init)) {
11176
+ return true;
11177
+ }
11178
+ }
11179
+ return false;
11180
+ }
10831
11181
  // Patterns are only checked at the empty path at the moment
10832
11182
  hasEffectsOnInteractionAtPath(_path, interaction, context) {
10833
11183
  for (const element of this.elements) {
@@ -10836,12 +11186,38 @@ class ArrayPattern extends NodeBase {
10836
11186
  }
10837
11187
  return false;
10838
11188
  }
11189
+ includeDestructuredIfNecessary(context, destructuredInitPath, init) {
11190
+ let included = false;
11191
+ const includedPatternPath = getIncludedPatternPath(destructuredInitPath);
11192
+ for (const element of this.elements) {
11193
+ if (element) {
11194
+ element.included ||= included;
11195
+ included =
11196
+ element.includeDestructuredIfNecessary(context, includedPatternPath, init) || included;
11197
+ }
11198
+ }
11199
+ if (included) {
11200
+ // This is necessary so that if any pattern element is included, all are
11201
+ // included for proper deconflicting
11202
+ for (const element of this.elements) {
11203
+ if (element && !element.included) {
11204
+ element.included = true;
11205
+ element.includeDestructuredIfNecessary(context, includedPatternPath, init);
11206
+ }
11207
+ }
11208
+ }
11209
+ return (this.included ||= included);
11210
+ }
10839
11211
  markDeclarationReached() {
10840
11212
  for (const element of this.elements) {
10841
11213
  element?.markDeclarationReached();
10842
11214
  }
10843
11215
  }
10844
11216
  }
11217
+ ArrayPattern.prototype.includeNode = onlyIncludeSelf;
11218
+ const getIncludedPatternPath = (destructuredInitPath) => destructuredInitPath.at(-1) === UnknownKey
11219
+ ? destructuredInitPath
11220
+ : [...destructuredInitPath, UnknownInteger];
10845
11221
 
10846
11222
  class ArrowFunctionExpression extends FunctionBase {
10847
11223
  constructor() {
@@ -10858,8 +11234,6 @@ class ArrowFunctionExpression extends FunctionBase {
10858
11234
  this.scope = new ReturnValueScope(parentScope, false);
10859
11235
  }
10860
11236
  hasEffects() {
10861
- if (!this.deoptimized)
10862
- this.applyDeoptimizations();
10863
11237
  return false;
10864
11238
  }
10865
11239
  hasEffectsOnInteractionAtPath(path, interaction, context) {
@@ -10898,6 +11272,15 @@ class ArrowFunctionExpression extends FunctionBase {
10898
11272
  }
10899
11273
  }
10900
11274
  }
11275
+ includeNode(context) {
11276
+ this.included = true;
11277
+ this.body.includePath(UNKNOWN_PATH, context);
11278
+ for (const parameter of this.params) {
11279
+ if (!(parameter instanceof Identifier)) {
11280
+ parameter.includePath(UNKNOWN_PATH, context);
11281
+ }
11282
+ }
11283
+ }
10901
11284
  getObjectEntity() {
10902
11285
  if (this.objectEntity !== null) {
10903
11286
  return this.objectEntity;
@@ -10917,13 +11300,18 @@ class ObjectPattern extends NodeBase {
10917
11300
  }
10918
11301
  }
10919
11302
  }
10920
- declare(kind, init) {
11303
+ declare(kind, destructuredInitPath, init) {
10921
11304
  const variables = [];
10922
11305
  for (const property of this.properties) {
10923
- variables.push(...property.declare(kind, init));
11306
+ variables.push(...property.declare(kind, destructuredInitPath, init));
10924
11307
  }
10925
11308
  return variables;
10926
11309
  }
11310
+ deoptimizeAssignment(destructuredInitPath, init) {
11311
+ for (const property of this.properties) {
11312
+ property.deoptimizeAssignment(destructuredInitPath, init);
11313
+ }
11314
+ }
10927
11315
  deoptimizePath(path) {
10928
11316
  if (path.length === 0) {
10929
11317
  for (const property of this.properties) {
@@ -10941,12 +11329,46 @@ class ObjectPattern extends NodeBase {
10941
11329
  }
10942
11330
  return false;
10943
11331
  }
11332
+ hasEffectsWhenDestructuring(context, destructuredInitPath, init) {
11333
+ for (const property of this.properties) {
11334
+ if (property.hasEffectsWhenDestructuring(context, destructuredInitPath, init))
11335
+ return true;
11336
+ }
11337
+ return false;
11338
+ }
11339
+ includeDestructuredIfNecessary(context, destructuredInitPath, init) {
11340
+ let included = false;
11341
+ for (const property of this.properties) {
11342
+ included =
11343
+ property.includeDestructuredIfNecessary(context, destructuredInitPath, init) || included;
11344
+ }
11345
+ return (this.included ||= included);
11346
+ }
10944
11347
  markDeclarationReached() {
10945
11348
  for (const property of this.properties) {
10946
11349
  property.markDeclarationReached();
10947
11350
  }
10948
11351
  }
11352
+ render(code, options) {
11353
+ if (this.properties.length > 0) {
11354
+ const separatedNodes = getCommaSeparatedNodesWithBoundaries(this.properties, code, this.start + 1, this.end - 1);
11355
+ let lastSeparatorPos = null;
11356
+ for (const { node, separator, start, end } of separatedNodes) {
11357
+ if (!node.included) {
11358
+ treeshakeNode(node, code, start, end);
11359
+ continue;
11360
+ }
11361
+ lastSeparatorPos = separator;
11362
+ node.render(code, options);
11363
+ }
11364
+ if (lastSeparatorPos) {
11365
+ code.remove(lastSeparatorPos, this.end - 1);
11366
+ }
11367
+ }
11368
+ }
10949
11369
  }
11370
+ ObjectPattern.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
11371
+ ObjectPattern.prototype.applyDeoptimizations = doNotDeoptimize;
10950
11372
 
10951
11373
  class AssignmentExpression extends NodeBase {
10952
11374
  hasEffects(context) {
@@ -10955,7 +11377,9 @@ class AssignmentExpression extends NodeBase {
10955
11377
  this.applyDeoptimizations();
10956
11378
  // MemberExpressions do not access the property before assignments if the
10957
11379
  // operator is '='.
10958
- return (right.hasEffects(context) || left.hasEffectsAsAssignmentTarget(context, operator !== '='));
11380
+ return (right.hasEffects(context) ||
11381
+ left.hasEffectsAsAssignmentTarget(context, operator !== '=') ||
11382
+ this.left.hasEffectsWhenDestructuring?.(context, EMPTY_PATH, right));
10959
11383
  }
10960
11384
  hasEffectsOnInteractionAtPath(path, interaction, context) {
10961
11385
  return this.right.hasEffectsOnInteractionAtPath(path, interaction, context);
@@ -10964,15 +11388,24 @@ class AssignmentExpression extends NodeBase {
10964
11388
  const { deoptimized, left, right, operator } = this;
10965
11389
  if (!deoptimized)
10966
11390
  this.applyDeoptimizations();
10967
- this.included = true;
11391
+ if (!this.included)
11392
+ this.includeNode(context);
11393
+ const hasEffectsContext = createHasEffectsContext();
10968
11394
  if (includeChildrenRecursively ||
10969
11395
  operator !== '=' ||
10970
11396
  left.included ||
10971
- left.hasEffectsAsAssignmentTarget(createHasEffectsContext(), false)) {
11397
+ left.hasEffectsAsAssignmentTarget(hasEffectsContext, false) ||
11398
+ left.hasEffectsWhenDestructuring?.(hasEffectsContext, EMPTY_PATH, right)) {
10972
11399
  left.includeAsAssignmentTarget(context, includeChildrenRecursively, operator !== '=');
10973
11400
  }
10974
11401
  right.include(context, includeChildrenRecursively);
10975
11402
  }
11403
+ includeNode(context) {
11404
+ this.included = true;
11405
+ if (!this.deoptimized)
11406
+ this.applyDeoptimizations();
11407
+ this.right.includePath(UNKNOWN_PATH, context);
11408
+ }
10976
11409
  initialise() {
10977
11410
  super.initialise();
10978
11411
  if (this.left instanceof Identifier) {
@@ -11033,8 +11466,7 @@ class AssignmentExpression extends NodeBase {
11033
11466
  }
11034
11467
  applyDeoptimizations() {
11035
11468
  this.deoptimized = true;
11036
- this.left.deoptimizePath(EMPTY_PATH);
11037
- this.right.deoptimizePath(UNKNOWN_PATH);
11469
+ this.left.deoptimizeAssignment(EMPTY_PATH, this.right);
11038
11470
  this.scope.context.requestTreeshakingPass();
11039
11471
  }
11040
11472
  }
@@ -11043,8 +11475,11 @@ class AssignmentPattern extends NodeBase {
11043
11475
  addExportedVariables(variables, exportNamesByVariable) {
11044
11476
  this.left.addExportedVariables(variables, exportNamesByVariable);
11045
11477
  }
11046
- declare(kind, init) {
11047
- return this.left.declare(kind, init);
11478
+ declare(kind, destructuredInitPath, init) {
11479
+ return this.left.declare(kind, destructuredInitPath, init);
11480
+ }
11481
+ deoptimizeAssignment(destructuredInitPath, init) {
11482
+ this.left.deoptimizeAssignment(destructuredInitPath, init);
11048
11483
  }
11049
11484
  deoptimizePath(path) {
11050
11485
  if (path.length === 0) {
@@ -11054,6 +11489,29 @@ class AssignmentPattern extends NodeBase {
11054
11489
  hasEffectsOnInteractionAtPath(path, interaction, context) {
11055
11490
  return (path.length > 0 || this.left.hasEffectsOnInteractionAtPath(EMPTY_PATH, interaction, context));
11056
11491
  }
11492
+ hasEffectsWhenDestructuring(context, destructuredInitPath, init) {
11493
+ return this.left.hasEffectsWhenDestructuring(context, destructuredInitPath, init);
11494
+ }
11495
+ includeDestructuredIfNecessary(context, destructuredInitPath, init) {
11496
+ let included = this.left.includeDestructuredIfNecessary(context, destructuredInitPath, init) ||
11497
+ this.included;
11498
+ if ((included ||= this.right.shouldBeIncluded(context))) {
11499
+ this.right.include(context, false);
11500
+ if (!this.left.included) {
11501
+ this.left.included = true;
11502
+ // Unfortunately, we need to include the left side again now, so that
11503
+ // any declared variables are properly included.
11504
+ this.left.includeDestructuredIfNecessary(context, destructuredInitPath, init);
11505
+ }
11506
+ }
11507
+ return (this.included = included);
11508
+ }
11509
+ includeNode(context) {
11510
+ this.included = true;
11511
+ if (!this.deoptimized)
11512
+ this.applyDeoptimizations();
11513
+ this.right.includePath(UNKNOWN_PATH, context);
11514
+ }
11057
11515
  markDeclarationReached() {
11058
11516
  this.left.markDeclarationReached();
11059
11517
  }
@@ -11076,22 +11534,34 @@ class AwaitExpression extends NodeBase {
11076
11534
  return true;
11077
11535
  }
11078
11536
  include(context, includeChildrenRecursively) {
11537
+ if (!this.included)
11538
+ this.includeNode(context);
11539
+ this.argument.include(context, includeChildrenRecursively);
11540
+ }
11541
+ includeNode(context) {
11542
+ this.included = true;
11079
11543
  if (!this.deoptimized)
11080
11544
  this.applyDeoptimizations();
11081
- if (!this.included) {
11082
- this.included = true;
11083
- checkTopLevelAwait: if (!this.scope.context.usesTopLevelAwait) {
11084
- let parent = this.parent;
11085
- do {
11086
- if (parent instanceof FunctionNode || parent instanceof ArrowFunctionExpression)
11087
- break checkTopLevelAwait;
11088
- } while ((parent = parent.parent));
11089
- this.scope.context.usesTopLevelAwait = true;
11090
- }
11545
+ checkTopLevelAwait: if (!this.scope.context.usesTopLevelAwait) {
11546
+ let parent = this.parent;
11547
+ do {
11548
+ if (parent instanceof FunctionNode || parent instanceof ArrowFunctionExpression)
11549
+ break checkTopLevelAwait;
11550
+ } while ((parent = parent.parent));
11551
+ this.scope.context.usesTopLevelAwait = true;
11091
11552
  }
11092
- this.argument.include(context, includeChildrenRecursively);
11553
+ // Thenables need to be included
11554
+ this.argument.includePath(THEN_PATH, context);
11555
+ }
11556
+ includePath(path, context) {
11557
+ if (!this.deoptimized)
11558
+ this.applyDeoptimizations();
11559
+ if (!this.included)
11560
+ this.includeNode(context);
11561
+ this.argument.includePath(path, context);
11093
11562
  }
11094
11563
  }
11564
+ const THEN_PATH = ['then'];
11095
11565
 
11096
11566
  const binaryOperators = {
11097
11567
  '!=': (left, right) => left != right,
@@ -11147,6 +11617,12 @@ class BinaryExpression extends NodeBase {
11147
11617
  hasEffectsOnInteractionAtPath(path, { type }) {
11148
11618
  return type !== INTERACTION_ACCESSED || path.length > 1;
11149
11619
  }
11620
+ includeNode(context) {
11621
+ this.included = true;
11622
+ if (this.operator === 'in') {
11623
+ this.right.includePath(UNKNOWN_PATH, context);
11624
+ }
11625
+ }
11150
11626
  removeAnnotations(code) {
11151
11627
  this.left.removeAnnotations(code);
11152
11628
  }
@@ -11155,6 +11631,7 @@ class BinaryExpression extends NodeBase {
11155
11631
  this.right.render(code, options);
11156
11632
  }
11157
11633
  }
11634
+ BinaryExpression.prototype.applyDeoptimizations = doNotDeoptimize;
11158
11635
 
11159
11636
  class BreakStatement extends NodeBase {
11160
11637
  hasEffects(context) {
@@ -11174,7 +11651,7 @@ class BreakStatement extends NodeBase {
11174
11651
  include(context) {
11175
11652
  this.included = true;
11176
11653
  if (this.label) {
11177
- this.label.include();
11654
+ this.label.include(context);
11178
11655
  context.includedLabels.add(this.label.name);
11179
11656
  }
11180
11657
  else {
@@ -11183,6 +11660,8 @@ class BreakStatement extends NodeBase {
11183
11660
  context.brokenFlow = true;
11184
11661
  }
11185
11662
  }
11663
+ BreakStatement.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
11664
+ BreakStatement.prototype.applyDeoptimizations = doNotDeoptimize;
11186
11665
 
11187
11666
  function renderCallArguments(code, options, node) {
11188
11667
  if (node.arguments.length > 0) {
@@ -11369,10 +11848,14 @@ class CallExpression extends CallExpressionBase {
11369
11848
  this.callee.hasEffectsOnInteractionAtPath(EMPTY_PATH, this.interaction, context)));
11370
11849
  }
11371
11850
  include(context, includeChildrenRecursively) {
11372
- if (!this.deoptimized)
11373
- this.applyDeoptimizations();
11851
+ if (!this.included)
11852
+ this.includeNode(context);
11374
11853
  if (includeChildrenRecursively) {
11375
- super.include(context, includeChildrenRecursively);
11854
+ this.callee.include(context, true);
11855
+ for (const argument of this.arguments) {
11856
+ argument.includePath(UNKNOWN_PATH, context);
11857
+ argument.include(context, true);
11858
+ }
11376
11859
  if (includeChildrenRecursively === INCLUDE_PARAMETERS &&
11377
11860
  this.callee instanceof Identifier &&
11378
11861
  this.callee.variable) {
@@ -11380,10 +11863,24 @@ class CallExpression extends CallExpressionBase {
11380
11863
  }
11381
11864
  }
11382
11865
  else {
11383
- this.included = true;
11384
- this.callee.include(context, false);
11866
+ // If the callee is a member expression and does not have a variable, its
11867
+ // object will already be included via the first argument of the
11868
+ // interaction in includeCallArguments. Including it again can lead to
11869
+ // severe performance problems.
11870
+ if (this.callee instanceof MemberExpression && !this.callee.variable) {
11871
+ this.callee.property.include(context, false);
11872
+ }
11873
+ else {
11874
+ this.callee.include(context, false);
11875
+ }
11876
+ this.callee.includeCallArguments(context, this.interaction);
11385
11877
  }
11386
- this.callee.includeCallArguments(context, this.arguments);
11878
+ }
11879
+ includeNode(context) {
11880
+ this.included = true;
11881
+ if (!this.deoptimized)
11882
+ this.applyDeoptimizations();
11883
+ this.callee.includePath(UNKNOWN_PATH, context);
11387
11884
  }
11388
11885
  initialise() {
11389
11886
  super.initialise();
@@ -11422,13 +11919,14 @@ class CatchClause extends NodeBase {
11422
11919
  this.type = type;
11423
11920
  if (param) {
11424
11921
  this.param = new (this.scope.context.getNodeConstructor(param.type))(this, this.scope).parseNode(param);
11425
- this.param.declare('parameter', UNKNOWN_EXPRESSION);
11922
+ this.param.declare('parameter', EMPTY_PATH, UNKNOWN_EXPRESSION);
11426
11923
  }
11427
11924
  this.body = new BlockStatement(this, this.scope.bodyScope).parseNode(body);
11428
11925
  return super.parseNode(esTreeNode);
11429
11926
  }
11430
11927
  }
11431
11928
  CatchClause.prototype.preventChildBlockScope = true;
11929
+ CatchClause.prototype.includeNode = onlyIncludeSelf;
11432
11930
 
11433
11931
  class ChainExpression extends NodeBase {
11434
11932
  // deoptimizations are not relevant as we are not caching values
@@ -11440,17 +11938,22 @@ class ChainExpression extends NodeBase {
11440
11938
  hasEffects(context) {
11441
11939
  return this.expression.hasEffectsAsChainElement(context) === true;
11442
11940
  }
11941
+ includePath(path, context) {
11942
+ this.included = true;
11943
+ this.expression.includePath(path, context);
11944
+ }
11443
11945
  removeAnnotations(code) {
11444
11946
  this.expression.removeAnnotations(code);
11445
11947
  }
11446
- applyDeoptimizations() { }
11447
11948
  }
11949
+ ChainExpression.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
11950
+ ChainExpression.prototype.applyDeoptimizations = doNotDeoptimize;
11448
11951
 
11449
11952
  class ClassBodyScope extends ChildScope {
11450
11953
  constructor(parent, classNode) {
11451
11954
  const { context } = parent;
11452
11955
  super(parent, context);
11453
- this.variables.set('this', (this.thisVariable = new LocalVariable('this', null, classNode, context, 'other')));
11956
+ this.variables.set('this', (this.thisVariable = new LocalVariable('this', null, classNode, EMPTY_PATH, context, 'other')));
11454
11957
  this.instanceScope = new ChildScope(this, context);
11455
11958
  this.instanceScope.variables.set('this', new ThisVariable(context));
11456
11959
  }
@@ -11465,7 +11968,7 @@ class ClassBody extends NodeBase {
11465
11968
  }
11466
11969
  include(context, includeChildrenRecursively) {
11467
11970
  this.included = true;
11468
- this.scope.context.includeVariableInModule(this.scope.thisVariable);
11971
+ this.scope.context.includeVariableInModule(this.scope.thisVariable, UNKNOWN_PATH, context);
11469
11972
  for (const definition of this.body) {
11470
11973
  definition.include(context, includeChildrenRecursively);
11471
11974
  }
@@ -11478,8 +11981,9 @@ class ClassBody extends NodeBase {
11478
11981
  }
11479
11982
  return super.parseNode(esTreeNode);
11480
11983
  }
11481
- applyDeoptimizations() { }
11482
11984
  }
11985
+ ClassBody.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
11986
+ ClassBody.prototype.applyDeoptimizations = doNotDeoptimize;
11483
11987
 
11484
11988
  class ClassExpression extends ClassNode {
11485
11989
  render(code, options, { renderedSurroundingElement } = BLANK) {
@@ -11550,6 +12054,9 @@ class ConditionalExpression extends NodeBase {
11550
12054
  const unusedBranch = this.usedBranch === this.consequent ? this.alternate : this.consequent;
11551
12055
  this.usedBranch = null;
11552
12056
  unusedBranch.deoptimizePath(UNKNOWN_PATH);
12057
+ if (this.included) {
12058
+ unusedBranch.includePath(UNKNOWN_PATH, createInclusionContext());
12059
+ }
11553
12060
  const { expressionsToBeDeoptimized } = this;
11554
12061
  this.expressionsToBeDeoptimized = EMPTY_ARRAY;
11555
12062
  for (const expression of expressionsToBeDeoptimized) {
@@ -11607,7 +12114,7 @@ class ConditionalExpression extends NodeBase {
11607
12114
  include(context, includeChildrenRecursively) {
11608
12115
  this.included = true;
11609
12116
  const usedBranch = this.getUsedBranch();
11610
- if (includeChildrenRecursively || this.test.shouldBeIncluded(context) || usedBranch === null) {
12117
+ if (usedBranch === null || includeChildrenRecursively || this.test.shouldBeIncluded(context)) {
11611
12118
  this.test.include(context, includeChildrenRecursively);
11612
12119
  this.consequent.include(context, includeChildrenRecursively);
11613
12120
  this.alternate.include(context, includeChildrenRecursively);
@@ -11616,27 +12123,38 @@ class ConditionalExpression extends NodeBase {
11616
12123
  usedBranch.include(context, includeChildrenRecursively);
11617
12124
  }
11618
12125
  }
11619
- includeCallArguments(context, parameters) {
12126
+ includePath(path, context) {
12127
+ this.included = true;
12128
+ const usedBranch = this.getUsedBranch();
12129
+ if (usedBranch === null || this.test.shouldBeIncluded(context)) {
12130
+ this.consequent.includePath(path, context);
12131
+ this.alternate.includePath(path, context);
12132
+ }
12133
+ else {
12134
+ usedBranch.includePath(path, context);
12135
+ }
12136
+ }
12137
+ includeCallArguments(context, interaction) {
11620
12138
  const usedBranch = this.getUsedBranch();
11621
12139
  if (usedBranch) {
11622
- usedBranch.includeCallArguments(context, parameters);
12140
+ usedBranch.includeCallArguments(context, interaction);
11623
12141
  }
11624
12142
  else {
11625
- this.consequent.includeCallArguments(context, parameters);
11626
- this.alternate.includeCallArguments(context, parameters);
12143
+ this.consequent.includeCallArguments(context, interaction);
12144
+ this.alternate.includeCallArguments(context, interaction);
11627
12145
  }
11628
12146
  }
11629
12147
  removeAnnotations(code) {
11630
12148
  this.test.removeAnnotations(code);
11631
12149
  }
11632
12150
  render(code, options, { isCalleeOfRenderedParent, preventASI, renderedParentType, renderedSurroundingElement } = BLANK) {
11633
- const usedBranch = this.getUsedBranch();
11634
12151
  if (this.test.included) {
11635
12152
  this.test.render(code, options, { renderedSurroundingElement });
11636
12153
  this.consequent.render(code, options);
11637
12154
  this.alternate.render(code, options);
11638
12155
  }
11639
12156
  else {
12157
+ const usedBranch = this.getUsedBranch();
11640
12158
  const colonPos = findFirstOccurrenceOutsideComment(code.original, ':', this.consequent.end);
11641
12159
  const inclusionStart = findNonWhiteSpace(code.original, (this.consequent.included
11642
12160
  ? findFirstOccurrenceOutsideComment(code.original, '?', this.test.end)
@@ -11668,6 +12186,8 @@ class ConditionalExpression extends NodeBase {
11668
12186
  : (this.usedBranch = testValue ? this.consequent : this.alternate);
11669
12187
  }
11670
12188
  }
12189
+ ConditionalExpression.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
12190
+ ConditionalExpression.prototype.applyDeoptimizations = doNotDeoptimize;
11671
12191
 
11672
12192
  class ContinueStatement extends NodeBase {
11673
12193
  hasEffects(context) {
@@ -11687,7 +12207,7 @@ class ContinueStatement extends NodeBase {
11687
12207
  include(context) {
11688
12208
  this.included = true;
11689
12209
  if (this.label) {
11690
- this.label.include();
12210
+ this.label.include(context);
11691
12211
  context.includedLabels.add(this.label.name);
11692
12212
  }
11693
12213
  else {
@@ -11696,12 +12216,15 @@ class ContinueStatement extends NodeBase {
11696
12216
  context.brokenFlow = true;
11697
12217
  }
11698
12218
  }
12219
+ ContinueStatement.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
12220
+ ContinueStatement.prototype.applyDeoptimizations = doNotDeoptimize;
11699
12221
 
11700
12222
  class DebuggerStatement extends NodeBase {
11701
12223
  hasEffects() {
11702
12224
  return true;
11703
12225
  }
11704
12226
  }
12227
+ DebuggerStatement.prototype.includeNode = onlyIncludeSelf;
11705
12228
 
11706
12229
  class Decorator extends NodeBase {
11707
12230
  hasEffects(context) {
@@ -11709,6 +12232,7 @@ class Decorator extends NodeBase {
11709
12232
  this.expression.hasEffectsOnInteractionAtPath(EMPTY_PATH, NODE_INTERACTION_UNKNOWN_CALL, context));
11710
12233
  }
11711
12234
  }
12235
+ Decorator.prototype.includeNode = onlyIncludeSelf;
11712
12236
 
11713
12237
  function hasLoopBodyEffects(context, body) {
11714
12238
  const { brokenFlow, hasBreak, hasContinue, ignore } = context;
@@ -11748,12 +12272,15 @@ class DoWhileStatement extends NodeBase {
11748
12272
  includeLoopBody(context, this.body, includeChildrenRecursively);
11749
12273
  }
11750
12274
  }
12275
+ DoWhileStatement.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
12276
+ DoWhileStatement.prototype.applyDeoptimizations = doNotDeoptimize;
11751
12277
 
11752
12278
  class EmptyStatement extends NodeBase {
11753
12279
  hasEffects() {
11754
12280
  return false;
11755
12281
  }
11756
12282
  }
12283
+ EmptyStatement.prototype.includeNode = onlyIncludeSelf;
11757
12284
 
11758
12285
  class ExportAllDeclaration extends NodeBase {
11759
12286
  hasEffects() {
@@ -11766,9 +12293,10 @@ class ExportAllDeclaration extends NodeBase {
11766
12293
  render(code, _options, nodeRenderOptions) {
11767
12294
  code.remove(nodeRenderOptions.start, nodeRenderOptions.end);
11768
12295
  }
11769
- applyDeoptimizations() { }
11770
12296
  }
11771
12297
  ExportAllDeclaration.prototype.needsBoundaries = true;
12298
+ ExportAllDeclaration.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
12299
+ ExportAllDeclaration.prototype.applyDeoptimizations = doNotDeoptimize;
11772
12300
 
11773
12301
  class ExportNamedDeclaration extends NodeBase {
11774
12302
  bind() {
@@ -11795,13 +12323,15 @@ class ExportNamedDeclaration extends NodeBase {
11795
12323
  this.declaration.render(code, options, { end, start });
11796
12324
  }
11797
12325
  }
11798
- applyDeoptimizations() { }
11799
12326
  }
11800
12327
  ExportNamedDeclaration.prototype.needsBoundaries = true;
12328
+ ExportNamedDeclaration.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
12329
+ ExportNamedDeclaration.prototype.applyDeoptimizations = doNotDeoptimize;
11801
12330
 
11802
12331
  class ExportSpecifier extends NodeBase {
11803
- applyDeoptimizations() { }
11804
12332
  }
12333
+ ExportSpecifier.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
12334
+ ExportSpecifier.prototype.applyDeoptimizations = doNotDeoptimize;
11805
12335
 
11806
12336
  class ForInStatement extends NodeBase {
11807
12337
  createScope(parentScope) {
@@ -11819,11 +12349,18 @@ class ForInStatement extends NodeBase {
11819
12349
  const { body, deoptimized, left, right } = this;
11820
12350
  if (!deoptimized)
11821
12351
  this.applyDeoptimizations();
11822
- this.included = true;
12352
+ if (!this.included)
12353
+ this.includeNode(context);
11823
12354
  left.includeAsAssignmentTarget(context, includeChildrenRecursively || true, false);
11824
12355
  right.include(context, includeChildrenRecursively);
11825
12356
  includeLoopBody(context, body, includeChildrenRecursively);
11826
12357
  }
12358
+ includeNode(context) {
12359
+ this.included = true;
12360
+ if (!this.deoptimized)
12361
+ this.applyDeoptimizations();
12362
+ this.right.includePath(UNKNOWN_PATH, context);
12363
+ }
11827
12364
  initialise() {
11828
12365
  super.initialise();
11829
12366
  this.left.setAssignedValue(UNKNOWN_EXPRESSION);
@@ -11864,11 +12401,18 @@ class ForOfStatement extends NodeBase {
11864
12401
  const { body, deoptimized, left, right } = this;
11865
12402
  if (!deoptimized)
11866
12403
  this.applyDeoptimizations();
11867
- this.included = true;
12404
+ if (!this.included)
12405
+ this.includeNode(context);
11868
12406
  left.includeAsAssignmentTarget(context, includeChildrenRecursively || true, false);
11869
12407
  right.include(context, includeChildrenRecursively);
11870
12408
  includeLoopBody(context, body, includeChildrenRecursively);
11871
12409
  }
12410
+ includeNode(context) {
12411
+ this.included = true;
12412
+ if (!this.deoptimized)
12413
+ this.applyDeoptimizations();
12414
+ this.right.includePath(UNKNOWN_PATH, context);
12415
+ }
11872
12416
  initialise() {
11873
12417
  super.initialise();
11874
12418
  this.left.setAssignedValue(UNKNOWN_EXPRESSION);
@@ -11904,7 +12448,9 @@ class ForStatement extends NodeBase {
11904
12448
  }
11905
12449
  include(context, includeChildrenRecursively) {
11906
12450
  this.included = true;
11907
- this.init?.include(context, includeChildrenRecursively, { asSingleStatement: true });
12451
+ this.init?.include(context, includeChildrenRecursively, {
12452
+ asSingleStatement: true
12453
+ });
11908
12454
  this.test?.include(context, includeChildrenRecursively);
11909
12455
  this.update?.include(context, includeChildrenRecursively);
11910
12456
  includeLoopBody(context, this.body, includeChildrenRecursively);
@@ -11916,6 +12462,8 @@ class ForStatement extends NodeBase {
11916
12462
  this.body.render(code, options);
11917
12463
  }
11918
12464
  }
12465
+ ForStatement.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
12466
+ ForStatement.prototype.applyDeoptimizations = doNotDeoptimize;
11919
12467
 
11920
12468
  class FunctionExpression extends FunctionNode {
11921
12469
  createScope(parentScope) {
@@ -11947,9 +12495,9 @@ class TrackingScope extends BlockScope {
11947
12495
  super(...arguments);
11948
12496
  this.hoistedDeclarations = [];
11949
12497
  }
11950
- addDeclaration(identifier, context, init, kind) {
12498
+ addDeclaration(identifier, context, init, destructuredInitPath, kind) {
11951
12499
  this.hoistedDeclarations.push(identifier);
11952
- return super.addDeclaration(identifier, context, init, kind);
12500
+ return super.addDeclaration(identifier, context, init, destructuredInitPath, kind);
11953
12501
  }
11954
12502
  }
11955
12503
 
@@ -12048,7 +12596,6 @@ class IfStatement extends NodeBase {
12048
12596
  }
12049
12597
  this.renderHoistedDeclarations(hoistedDeclarations, code, getPropertyAccess);
12050
12598
  }
12051
- applyDeoptimizations() { }
12052
12599
  getTestValue() {
12053
12600
  if (this.testValue === unset) {
12054
12601
  return (this.testValue = tryCastLiteralValueToBoolean(this.test.getLiteralValueAtPath(EMPTY_PATH, SHARED_RECURSION_TRACKER, this)));
@@ -12117,6 +12664,8 @@ class IfStatement extends NodeBase {
12117
12664
  return false;
12118
12665
  }
12119
12666
  }
12667
+ IfStatement.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
12668
+ IfStatement.prototype.applyDeoptimizations = doNotDeoptimize;
12120
12669
 
12121
12670
  class ImportAttribute extends NodeBase {
12122
12671
  }
@@ -12134,13 +12683,15 @@ class ImportDeclaration extends NodeBase {
12134
12683
  render(code, _options, nodeRenderOptions) {
12135
12684
  code.remove(nodeRenderOptions.start, nodeRenderOptions.end);
12136
12685
  }
12137
- applyDeoptimizations() { }
12138
12686
  }
12139
12687
  ImportDeclaration.prototype.needsBoundaries = true;
12688
+ ImportDeclaration.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
12689
+ ImportDeclaration.prototype.applyDeoptimizations = doNotDeoptimize;
12140
12690
 
12141
12691
  class ImportDefaultSpecifier extends NodeBase {
12142
- applyDeoptimizations() { }
12143
12692
  }
12693
+ ImportDefaultSpecifier.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
12694
+ ImportDefaultSpecifier.prototype.applyDeoptimizations = doNotDeoptimize;
12144
12695
 
12145
12696
  function isReassignedExportsMember(variable, exportNamesByVariable) {
12146
12697
  return (variable.renderBaseName !== null && exportNamesByVariable.has(variable) && variable.isReassigned);
@@ -12149,28 +12700,33 @@ function isReassignedExportsMember(variable, exportNamesByVariable) {
12149
12700
  class VariableDeclarator extends NodeBase {
12150
12701
  declareDeclarator(kind, isUsingDeclaration) {
12151
12702
  this.isUsingDeclaration = isUsingDeclaration;
12152
- this.id.declare(kind, this.init || UNDEFINED_EXPRESSION);
12703
+ this.id.declare(kind, EMPTY_PATH, this.init || UNDEFINED_EXPRESSION);
12153
12704
  }
12154
12705
  deoptimizePath(path) {
12155
12706
  this.id.deoptimizePath(path);
12156
12707
  }
12157
12708
  hasEffects(context) {
12158
- if (!this.deoptimized)
12159
- this.applyDeoptimizations();
12160
12709
  const initEffect = this.init?.hasEffects(context);
12161
12710
  this.id.markDeclarationReached();
12162
- return initEffect || this.id.hasEffects(context) || this.isUsingDeclaration;
12711
+ return (initEffect ||
12712
+ this.isUsingDeclaration ||
12713
+ this.id.hasEffects(context) ||
12714
+ (this.scope.context.options.treeshake
12715
+ .propertyReadSideEffects &&
12716
+ this.id.hasEffectsWhenDestructuring(context, EMPTY_PATH, this.init || UNDEFINED_EXPRESSION)));
12163
12717
  }
12164
12718
  include(context, includeChildrenRecursively) {
12165
- const { deoptimized, id, init } = this;
12166
- if (!deoptimized)
12167
- this.applyDeoptimizations();
12168
- this.included = true;
12719
+ const { id, init } = this;
12720
+ if (!this.included)
12721
+ this.includeNode();
12169
12722
  init?.include(context, includeChildrenRecursively);
12170
12723
  id.markDeclarationReached();
12171
- if (includeChildrenRecursively || id.shouldBeIncluded(context)) {
12724
+ if (includeChildrenRecursively) {
12172
12725
  id.include(context, includeChildrenRecursively);
12173
12726
  }
12727
+ else {
12728
+ id.includeDestructuredIfNecessary(context, EMPTY_PATH, init || UNDEFINED_EXPRESSION);
12729
+ }
12174
12730
  }
12175
12731
  removeAnnotations(code) {
12176
12732
  this.init?.removeAnnotations(code);
@@ -12200,8 +12756,8 @@ class VariableDeclarator extends NodeBase {
12200
12756
  code.appendLeft(end, `${_}=${_}void 0`);
12201
12757
  }
12202
12758
  }
12203
- applyDeoptimizations() {
12204
- this.deoptimized = true;
12759
+ includeNode() {
12760
+ this.included = true;
12205
12761
  const { id, init } = this;
12206
12762
  if (init && id instanceof Identifier && init instanceof ClassExpression && !init.id) {
12207
12763
  const { name, variable } = id;
@@ -12213,11 +12769,14 @@ class VariableDeclarator extends NodeBase {
12213
12769
  }
12214
12770
  }
12215
12771
  }
12772
+ VariableDeclarator.prototype.applyDeoptimizations = doNotDeoptimize;
12216
12773
 
12217
12774
  class ImportExpression extends NodeBase {
12218
12775
  constructor() {
12219
12776
  super(...arguments);
12220
12777
  this.inlineNamespace = null;
12778
+ this.hasUnknownAccessedKey = false;
12779
+ this.accessedPropKey = new Set();
12221
12780
  this.attributes = null;
12222
12781
  this.mechanism = null;
12223
12782
  this.namespaceExportName = undefined;
@@ -12250,12 +12809,15 @@ class ImportExpression extends NodeBase {
12250
12809
  if (parent2 instanceof ExpressionStatement) {
12251
12810
  return EMPTY_ARRAY;
12252
12811
  }
12253
- // Case 1: const { foo } = await import('bar')
12812
+ // Case 1: const { foo } / module = await import('bar')
12254
12813
  if (parent2 instanceof VariableDeclarator) {
12255
12814
  const declaration = parent2.id;
12256
- return declaration instanceof ObjectPattern
12257
- ? getDeterministicObjectDestructure(declaration)
12258
- : undefined;
12815
+ if (declaration instanceof Identifier) {
12816
+ return this.hasUnknownAccessedKey ? undefined : [...this.accessedPropKey];
12817
+ }
12818
+ if (declaration instanceof ObjectPattern) {
12819
+ return getDeterministicObjectDestructure(declaration);
12820
+ }
12259
12821
  }
12260
12822
  // Case 2: (await import('bar')).foo
12261
12823
  if (parent2 instanceof MemberExpression) {
@@ -12305,13 +12867,30 @@ class ImportExpression extends NodeBase {
12305
12867
  return true;
12306
12868
  }
12307
12869
  include(context, includeChildrenRecursively) {
12308
- if (!this.included) {
12309
- this.included = true;
12310
- this.scope.context.includeDynamicImport(this);
12311
- this.scope.addAccessedDynamicImport(this);
12312
- }
12870
+ if (!this.included)
12871
+ this.includeNode();
12313
12872
  this.source.include(context, includeChildrenRecursively);
12314
12873
  }
12874
+ includeNode() {
12875
+ this.included = true;
12876
+ this.scope.context.includeDynamicImport(this);
12877
+ this.scope.addAccessedDynamicImport(this);
12878
+ }
12879
+ includePath(path) {
12880
+ if (!this.included)
12881
+ this.includeNode();
12882
+ // Technically, this is not correct as dynamic imports return a Promise.
12883
+ if (this.hasUnknownAccessedKey)
12884
+ return;
12885
+ if (path[0] === UnknownKey) {
12886
+ this.hasUnknownAccessedKey = true;
12887
+ }
12888
+ else if (typeof path[0] === 'string') {
12889
+ this.accessedPropKey.add(path[0]);
12890
+ }
12891
+ // Update included paths
12892
+ this.scope.context.includeDynamicImport(this);
12893
+ }
12315
12894
  initialise() {
12316
12895
  super.initialise();
12317
12896
  this.scope.context.addDynamicImport(this);
@@ -12380,7 +12959,6 @@ class ImportExpression extends NodeBase {
12380
12959
  setInternalResolution(inlineNamespace) {
12381
12960
  this.inlineNamespace = inlineNamespace;
12382
12961
  }
12383
- applyDeoptimizations() { }
12384
12962
  getDynamicImportMechanismAndHelper(resolution, exportMode, { compact, dynamicImportInCjs, format, generatedCode: { arrowFunctions }, interop }, { _, getDirectReturnFunction, getDirectReturnIifeLeft }, pluginDriver) {
12385
12963
  const mechanism = pluginDriver.hookFirstSync('renderDynamicImport', [
12386
12964
  {
@@ -12470,6 +13048,7 @@ class ImportExpression extends NodeBase {
12470
13048
  return { helper: null, mechanism: null };
12471
13049
  }
12472
13050
  }
13051
+ ImportExpression.prototype.applyDeoptimizations = doNotDeoptimize;
12473
13052
  function getInteropHelper(resolution, exportMode, interop) {
12474
13053
  return exportMode === 'external'
12475
13054
  ? namespaceInteropHelpersByInteropType[interop(resolution instanceof ExternalModule ? resolution.id : null)]
@@ -12493,12 +13072,14 @@ function getDeterministicObjectDestructure(objectPattern) {
12493
13072
  }
12494
13073
 
12495
13074
  class ImportNamespaceSpecifier extends NodeBase {
12496
- applyDeoptimizations() { }
12497
13075
  }
13076
+ ImportNamespaceSpecifier.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
13077
+ ImportNamespaceSpecifier.prototype.applyDeoptimizations = doNotDeoptimize;
12498
13078
 
12499
13079
  class ImportSpecifier extends NodeBase {
12500
- applyDeoptimizations() { }
12501
13080
  }
13081
+ ImportSpecifier.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
13082
+ ImportSpecifier.prototype.applyDeoptimizations = doNotDeoptimize;
12502
13083
 
12503
13084
  class JSXIdentifier extends IdentifierBase {
12504
13085
  constructor() {
@@ -12515,6 +13096,29 @@ class JSXIdentifier extends IdentifierBase {
12515
13096
  this.isNativeElement = true;
12516
13097
  }
12517
13098
  }
13099
+ include(context) {
13100
+ if (!this.included)
13101
+ this.includeNode(context);
13102
+ }
13103
+ includeNode(context) {
13104
+ this.included = true;
13105
+ if (!this.deoptimized)
13106
+ this.applyDeoptimizations();
13107
+ if (this.variable !== null) {
13108
+ this.scope.context.includeVariableInModule(this.variable, EMPTY_PATH, context);
13109
+ }
13110
+ }
13111
+ includePath(path, context) {
13112
+ if (!this.included) {
13113
+ this.included = true;
13114
+ if (this.variable !== null) {
13115
+ this.scope.context.includeVariableInModule(this.variable, path, context);
13116
+ }
13117
+ }
13118
+ else if (path.length > 0) {
13119
+ this.variable?.includePath(path, context);
13120
+ }
13121
+ }
12518
13122
  render(code, { snippets: { getPropertyAccess }, useOriginalName }) {
12519
13123
  if (this.variable) {
12520
13124
  const name = this.variable.getName(getPropertyAccess, useOriginalName);
@@ -12576,6 +13180,7 @@ class JSXAttribute extends NodeBase {
12576
13180
  }
12577
13181
  }
12578
13182
  }
13183
+ JSXAttribute.prototype.includeNode = onlyIncludeSelf;
12579
13184
 
12580
13185
  class JSXClosingBase extends NodeBase {
12581
13186
  render(code, options) {
@@ -12588,6 +13193,7 @@ class JSXClosingBase extends NodeBase {
12588
13193
  }
12589
13194
  }
12590
13195
  }
13196
+ JSXClosingBase.prototype.includeNode = onlyIncludeSelf;
12591
13197
 
12592
13198
  class JSXClosingElement extends JSXClosingBase {
12593
13199
  }
@@ -12608,8 +13214,15 @@ class JSXSpreadAttribute extends NodeBase {
12608
13214
 
12609
13215
  class JSXEmptyExpression extends NodeBase {
12610
13216
  }
13217
+ JSXEmptyExpression.prototype.includeNode = onlyIncludeSelf;
12611
13218
 
12612
13219
  class JSXExpressionContainer extends NodeBase {
13220
+ includeNode(context) {
13221
+ this.included = true;
13222
+ if (!this.deoptimized)
13223
+ this.applyDeoptimizations();
13224
+ this.expression.includePath(UNKNOWN_PATH, context);
13225
+ }
12613
13226
  render(code, options) {
12614
13227
  const { mode } = this.scope.context.options.jsx;
12615
13228
  if (mode !== 'preserve') {
@@ -12630,7 +13243,7 @@ function getRenderedJsxChildren(children) {
12630
13243
  return renderedChildren;
12631
13244
  }
12632
13245
 
12633
- function getAndIncludeFactoryVariable(factory, preserve, importSource, node) {
13246
+ function getAndIncludeFactoryVariable(factory, preserve, importSource, node, context) {
12634
13247
  const [baseName, nestedName] = factory.split('.');
12635
13248
  let factoryVariable;
12636
13249
  if (importSource) {
@@ -12638,7 +13251,7 @@ function getAndIncludeFactoryVariable(factory, preserve, importSource, node) {
12638
13251
  if (preserve) {
12639
13252
  // This pretends we are accessing an included global variable of the same name
12640
13253
  const globalVariable = node.scope.findGlobal(baseName);
12641
- globalVariable.include();
13254
+ globalVariable.includePath(UNKNOWN_PATH, context);
12642
13255
  // This excludes this variable from renaming
12643
13256
  factoryVariable.globalName = baseName;
12644
13257
  }
@@ -12646,7 +13259,7 @@ function getAndIncludeFactoryVariable(factory, preserve, importSource, node) {
12646
13259
  else {
12647
13260
  factoryVariable = node.scope.findGlobal(baseName);
12648
13261
  }
12649
- node.scope.context.includeVariableInModule(factoryVariable);
13262
+ node.scope.context.includeVariableInModule(factoryVariable, UNKNOWN_PATH, context);
12650
13263
  if (factoryVariable instanceof LocalVariable) {
12651
13264
  factoryVariable.consolidateInitializers();
12652
13265
  factoryVariable.addUsedPlace(node);
@@ -12669,16 +13282,20 @@ class JSXElementBase extends NodeBase {
12669
13282
  }
12670
13283
  }
12671
13284
  include(context, includeChildrenRecursively) {
12672
- if (!this.included) {
12673
- const { factory, importSource, mode } = this.jsxMode;
12674
- if (factory) {
12675
- this.factory = factory;
12676
- this.factoryVariable = getAndIncludeFactoryVariable(factory, mode === 'preserve', importSource, this);
12677
- }
13285
+ if (!this.included)
13286
+ this.includeNode(context);
13287
+ for (const child of this.children) {
13288
+ child.include(context, includeChildrenRecursively);
13289
+ }
13290
+ }
13291
+ includeNode(context) {
13292
+ this.included = true;
13293
+ const { factory, importSource, mode } = this.jsxMode;
13294
+ if (factory) {
13295
+ this.factory = factory;
13296
+ this.factoryVariable = getAndIncludeFactoryVariable(factory, mode === 'preserve', importSource, this, context);
12678
13297
  }
12679
- super.include(context, includeChildrenRecursively);
12680
13298
  }
12681
- applyDeoptimizations() { }
12682
13299
  getRenderingMode() {
12683
13300
  const jsx = this.scope.context.options.jsx;
12684
13301
  const { mode, factory, importSource } = jsx;
@@ -12716,8 +13333,14 @@ class JSXElementBase extends NodeBase {
12716
13333
  return { childrenEnd, firstChild, hasMultipleChildren };
12717
13334
  }
12718
13335
  }
13336
+ JSXElementBase.prototype.applyDeoptimizations = doNotDeoptimize;
12719
13337
 
12720
13338
  class JSXElement extends JSXElementBase {
13339
+ include(context, includeChildrenRecursively) {
13340
+ super.include(context, includeChildrenRecursively);
13341
+ this.openingElement.include(context, includeChildrenRecursively);
13342
+ this.closingElement?.include(context, includeChildrenRecursively);
13343
+ }
12721
13344
  render(code, options) {
12722
13345
  switch (this.jsxMode.mode) {
12723
13346
  case 'classic': {
@@ -12869,6 +13492,11 @@ class JSXElement extends JSXElementBase {
12869
13492
  }
12870
13493
 
12871
13494
  class JSXFragment extends JSXElementBase {
13495
+ include(context, includeChildrenRecursively) {
13496
+ super.include(context, includeChildrenRecursively);
13497
+ this.openingFragment.include(context, includeChildrenRecursively);
13498
+ this.closingFragment.include(context, includeChildrenRecursively);
13499
+ }
12872
13500
  render(code, options) {
12873
13501
  switch (this.jsxMode.mode) {
12874
13502
  case 'classic': {
@@ -12918,10 +13546,22 @@ class JSXFragment extends JSXElementBase {
12918
13546
  }
12919
13547
 
12920
13548
  class JSXMemberExpression extends NodeBase {
13549
+ includeNode(context) {
13550
+ this.included = true;
13551
+ if (!this.deoptimized)
13552
+ this.applyDeoptimizations();
13553
+ this.object.includePath([this.property.name], context);
13554
+ }
13555
+ includePath(path, context) {
13556
+ if (!this.included)
13557
+ this.includeNode(context);
13558
+ this.object.includePath([this.property.name, ...path], context);
13559
+ }
12921
13560
  }
12922
13561
 
12923
13562
  class JSXNamespacedName extends NodeBase {
12924
13563
  }
13564
+ JSXNamespacedName.prototype.includeNode = onlyIncludeSelf;
12925
13565
 
12926
13566
  class JSXOpeningElement extends NodeBase {
12927
13567
  render(code, options, { jsxMode = this.scope.context.options.jsx.mode } = {}) {
@@ -12931,6 +13571,7 @@ class JSXOpeningElement extends NodeBase {
12931
13571
  }
12932
13572
  }
12933
13573
  }
13574
+ JSXOpeningElement.prototype.includeNode = onlyIncludeSelf;
12934
13575
 
12935
13576
  class JSXOpeningFragment extends NodeBase {
12936
13577
  constructor() {
@@ -12938,22 +13579,22 @@ class JSXOpeningFragment extends NodeBase {
12938
13579
  this.fragment = null;
12939
13580
  this.fragmentVariable = null;
12940
13581
  }
12941
- include(context, includeChildrenRecursively) {
12942
- if (!this.included) {
12943
- const jsx = this.scope.context.options.jsx;
12944
- if (jsx.mode === 'automatic') {
12945
- this.fragment = 'Fragment';
12946
- this.fragmentVariable = getAndIncludeFactoryVariable('Fragment', false, jsx.jsxImportSource, this);
12947
- }
12948
- else {
12949
- const { fragment, importSource, mode } = jsx;
12950
- if (fragment != null) {
12951
- this.fragment = fragment;
12952
- this.fragmentVariable = getAndIncludeFactoryVariable(fragment, mode === 'preserve', importSource, this);
12953
- }
13582
+ includeNode(context) {
13583
+ this.included = true;
13584
+ if (!this.deoptimized)
13585
+ this.applyDeoptimizations();
13586
+ const jsx = this.scope.context.options.jsx;
13587
+ if (jsx.mode === 'automatic') {
13588
+ this.fragment = 'Fragment';
13589
+ this.fragmentVariable = getAndIncludeFactoryVariable('Fragment', false, jsx.jsxImportSource, this, context);
13590
+ }
13591
+ else {
13592
+ const { fragment, importSource, mode } = jsx;
13593
+ if (fragment != null) {
13594
+ this.fragment = fragment;
13595
+ this.fragmentVariable = getAndIncludeFactoryVariable(fragment, mode === 'preserve', importSource, this, context);
12954
13596
  }
12955
13597
  }
12956
- super.include(context, includeChildrenRecursively);
12957
13598
  }
12958
13599
  render(code, options) {
12959
13600
  const { mode } = this.scope.context.options.jsx;
@@ -12990,6 +13631,7 @@ class JSXText extends NodeBase {
12990
13631
  }
12991
13632
  }
12992
13633
  }
13634
+ JSXText.prototype.includeNode = onlyIncludeSelf;
12993
13635
 
12994
13636
  class LabeledStatement extends NodeBase {
12995
13637
  hasEffects(context) {
@@ -13011,17 +13653,22 @@ class LabeledStatement extends NodeBase {
13011
13653
  return bodyHasEffects;
13012
13654
  }
13013
13655
  include(context, includeChildrenRecursively) {
13014
- this.included = true;
13656
+ if (!this.included)
13657
+ this.includeNode(context);
13015
13658
  const { brokenFlow, includedLabels } = context;
13016
13659
  context.includedLabels = new Set();
13017
13660
  this.body.include(context, includeChildrenRecursively);
13018
13661
  if (includeChildrenRecursively || context.includedLabels.has(this.label.name)) {
13019
- this.label.include();
13662
+ this.label.include(context);
13020
13663
  context.includedLabels.delete(this.label.name);
13021
13664
  context.brokenFlow = brokenFlow;
13022
13665
  }
13023
13666
  context.includedLabels = new Set([...includedLabels, ...context.includedLabels]);
13024
13667
  }
13668
+ includeNode(context) {
13669
+ this.included = true;
13670
+ this.body.includePath(UNKNOWN_PATH, context);
13671
+ }
13025
13672
  render(code, options) {
13026
13673
  if (this.label.included) {
13027
13674
  this.label.render(code, options);
@@ -13032,6 +13679,7 @@ class LabeledStatement extends NodeBase {
13032
13679
  this.body.render(code, options);
13033
13680
  }
13034
13681
  }
13682
+ LabeledStatement.prototype.applyDeoptimizations = doNotDeoptimize;
13035
13683
 
13036
13684
  class LogicalExpression extends NodeBase {
13037
13685
  constructor() {
@@ -13047,24 +13695,37 @@ class LogicalExpression extends NodeBase {
13047
13695
  set isBranchResolutionAnalysed(value) {
13048
13696
  this.flags = setFlag(this.flags, 65536 /* Flag.isBranchResolutionAnalysed */, value);
13049
13697
  }
13698
+ get hasDeoptimizedCache() {
13699
+ return isFlagSet(this.flags, 33554432 /* Flag.hasDeoptimizedCache */);
13700
+ }
13701
+ set hasDeoptimizedCache(value) {
13702
+ this.flags = setFlag(this.flags, 33554432 /* Flag.hasDeoptimizedCache */, value);
13703
+ }
13050
13704
  deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
13051
13705
  this.left.deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker);
13052
13706
  this.right.deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker);
13053
13707
  }
13054
13708
  deoptimizeCache() {
13709
+ if (this.hasDeoptimizedCache)
13710
+ return;
13055
13711
  if (this.usedBranch) {
13056
13712
  const unusedBranch = this.usedBranch === this.left ? this.right : this.left;
13057
13713
  this.usedBranch = null;
13058
13714
  unusedBranch.deoptimizePath(UNKNOWN_PATH);
13059
- const { scope: { context }, expressionsToBeDeoptimized } = this;
13060
- this.expressionsToBeDeoptimized = EMPTY_ARRAY;
13061
- for (const expression of expressionsToBeDeoptimized) {
13062
- expression.deoptimizeCache();
13715
+ if (this.included) {
13716
+ // As we are not tracking inclusions, we just include everything
13717
+ unusedBranch.includePath(UNKNOWN_PATH, createInclusionContext());
13063
13718
  }
13064
- // Request another pass because we need to ensure "include" runs again if
13065
- // it is rendered
13066
- context.requestTreeshakingPass();
13067
13719
  }
13720
+ const { scope: { context }, expressionsToBeDeoptimized } = this;
13721
+ this.expressionsToBeDeoptimized = EMPTY_ARRAY;
13722
+ for (const expression of expressionsToBeDeoptimized) {
13723
+ expression.deoptimizeCache();
13724
+ }
13725
+ // Request another pass because we need to ensure "include" runs again if
13726
+ // it is rendered
13727
+ context.requestTreeshakingPass();
13728
+ this.hasDeoptimizedCache = true;
13068
13729
  }
13069
13730
  deoptimizePath(path) {
13070
13731
  const usedBranch = this.getUsedBranch();
@@ -13082,7 +13743,7 @@ class LogicalExpression extends NodeBase {
13082
13743
  this.expressionsToBeDeoptimized.push(origin);
13083
13744
  return usedBranch.getLiteralValueAtPath(path, recursionTracker, origin);
13084
13745
  }
13085
- else {
13746
+ else if (!this.hasDeoptimizedCache) {
13086
13747
  const rightValue = this.right.getLiteralValueAtPath(path, recursionTracker, origin);
13087
13748
  const booleanOrUnknown = tryCastLiteralValueToBoolean(rightValue);
13088
13749
  if (typeof booleanOrUnknown !== 'symbol') {
@@ -13091,6 +13752,7 @@ class LogicalExpression extends NodeBase {
13091
13752
  return UnknownFalsyValue;
13092
13753
  }
13093
13754
  if (booleanOrUnknown && this.operator === '||') {
13755
+ this.expressionsToBeDeoptimized.push(origin);
13094
13756
  return UnknownTruthyValue;
13095
13757
  }
13096
13758
  }
@@ -13099,16 +13761,17 @@ class LogicalExpression extends NodeBase {
13099
13761
  }
13100
13762
  getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin) {
13101
13763
  const usedBranch = this.getUsedBranch();
13102
- if (!usedBranch)
13103
- return [
13104
- new MultiExpression([
13105
- this.left.getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin)[0],
13106
- this.right.getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin)[0]
13107
- ]),
13108
- false
13109
- ];
13110
- this.expressionsToBeDeoptimized.push(origin);
13111
- return usedBranch.getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin);
13764
+ if (usedBranch) {
13765
+ this.expressionsToBeDeoptimized.push(origin);
13766
+ return usedBranch.getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin);
13767
+ }
13768
+ return [
13769
+ new MultiExpression([
13770
+ this.left.getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin)[0],
13771
+ this.right.getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin)[0]
13772
+ ]),
13773
+ false
13774
+ ];
13112
13775
  }
13113
13776
  hasEffects(context) {
13114
13777
  if (this.left.hasEffects(context)) {
@@ -13121,18 +13784,18 @@ class LogicalExpression extends NodeBase {
13121
13784
  }
13122
13785
  hasEffectsOnInteractionAtPath(path, interaction, context) {
13123
13786
  const usedBranch = this.getUsedBranch();
13124
- if (!usedBranch) {
13125
- return (this.left.hasEffectsOnInteractionAtPath(path, interaction, context) ||
13126
- this.right.hasEffectsOnInteractionAtPath(path, interaction, context));
13787
+ if (usedBranch) {
13788
+ return usedBranch.hasEffectsOnInteractionAtPath(path, interaction, context);
13127
13789
  }
13128
- return usedBranch.hasEffectsOnInteractionAtPath(path, interaction, context);
13790
+ return (this.left.hasEffectsOnInteractionAtPath(path, interaction, context) ||
13791
+ this.right.hasEffectsOnInteractionAtPath(path, interaction, context));
13129
13792
  }
13130
13793
  include(context, includeChildrenRecursively) {
13131
13794
  this.included = true;
13132
13795
  const usedBranch = this.getUsedBranch();
13133
13796
  if (includeChildrenRecursively ||
13134
- (usedBranch === this.right && this.left.shouldBeIncluded(context)) ||
13135
- !usedBranch) {
13797
+ !usedBranch ||
13798
+ (usedBranch === this.right && this.left.shouldBeIncluded(context))) {
13136
13799
  this.left.include(context, includeChildrenRecursively);
13137
13800
  this.right.include(context, includeChildrenRecursively);
13138
13801
  }
@@ -13140,6 +13803,17 @@ class LogicalExpression extends NodeBase {
13140
13803
  usedBranch.include(context, includeChildrenRecursively);
13141
13804
  }
13142
13805
  }
13806
+ includePath(path, context) {
13807
+ this.included = true;
13808
+ const usedBranch = this.getUsedBranch();
13809
+ if (!usedBranch || (usedBranch === this.right && this.left.shouldBeIncluded(context))) {
13810
+ this.left.includePath(path, context);
13811
+ this.right.includePath(path, context);
13812
+ }
13813
+ else {
13814
+ usedBranch.includePath(path, context);
13815
+ }
13816
+ }
13143
13817
  removeAnnotations(code) {
13144
13818
  this.left.removeAnnotations(code);
13145
13819
  }
@@ -13192,6 +13866,8 @@ class LogicalExpression extends NodeBase {
13192
13866
  return this.usedBranch;
13193
13867
  }
13194
13868
  }
13869
+ LogicalExpression.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
13870
+ LogicalExpression.prototype.applyDeoptimizations = doNotDeoptimize;
13195
13871
 
13196
13872
  class NewExpression extends NodeBase {
13197
13873
  hasEffects(context) {
@@ -13211,16 +13887,21 @@ class NewExpression extends NodeBase {
13211
13887
  return path.length > 0 || type !== INTERACTION_ACCESSED;
13212
13888
  }
13213
13889
  include(context, includeChildrenRecursively) {
13214
- if (!this.deoptimized)
13215
- this.applyDeoptimizations();
13216
13890
  if (includeChildrenRecursively) {
13217
13891
  super.include(context, includeChildrenRecursively);
13218
13892
  }
13219
13893
  else {
13220
- this.included = true;
13894
+ if (!this.included)
13895
+ this.includeNode(context);
13221
13896
  this.callee.include(context, false);
13222
13897
  }
13223
- this.callee.includeCallArguments(context, this.arguments);
13898
+ this.callee.includeCallArguments(context, this.interaction);
13899
+ }
13900
+ includeNode(context) {
13901
+ this.included = true;
13902
+ if (!this.deoptimized)
13903
+ this.applyDeoptimizations();
13904
+ this.callee.includePath(UNKNOWN_PATH, context);
13224
13905
  }
13225
13906
  initialise() {
13226
13907
  super.initialise();
@@ -13249,6 +13930,7 @@ class ObjectExpression extends NodeBase {
13249
13930
  constructor() {
13250
13931
  super(...arguments);
13251
13932
  this.objectEntity = null;
13933
+ this.protoProp = null;
13252
13934
  }
13253
13935
  deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
13254
13936
  this.getObjectEntity().deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker);
@@ -13268,15 +13950,43 @@ class ObjectExpression extends NodeBase {
13268
13950
  hasEffectsOnInteractionAtPath(path, interaction, context) {
13269
13951
  return this.getObjectEntity().hasEffectsOnInteractionAtPath(path, interaction, context);
13270
13952
  }
13953
+ include(context, includeChildrenRecursively) {
13954
+ if (!this.included)
13955
+ this.includeNode(context);
13956
+ this.getObjectEntity().include(context, includeChildrenRecursively);
13957
+ this.protoProp?.include(context, includeChildrenRecursively);
13958
+ }
13959
+ includeNode(context) {
13960
+ this.included = true;
13961
+ this.protoProp?.includePath(UNKNOWN_PATH, context);
13962
+ }
13963
+ includePath(path, context) {
13964
+ if (!this.included)
13965
+ this.includeNode(context);
13966
+ this.getObjectEntity().includePath(path, context);
13967
+ }
13271
13968
  render(code, options, { renderedSurroundingElement } = BLANK) {
13272
- super.render(code, options);
13273
13969
  if (renderedSurroundingElement === ExpressionStatement$1 ||
13274
13970
  renderedSurroundingElement === ArrowFunctionExpression$1) {
13275
13971
  code.appendRight(this.start, '(');
13276
13972
  code.prependLeft(this.end, ')');
13277
13973
  }
13974
+ if (this.properties.length > 0) {
13975
+ const separatedNodes = getCommaSeparatedNodesWithBoundaries(this.properties, code, this.start + 1, this.end - 1);
13976
+ let lastSeparatorPos = null;
13977
+ for (const { node, separator, start, end } of separatedNodes) {
13978
+ if (!node.included) {
13979
+ treeshakeNode(node, code, start, end);
13980
+ continue;
13981
+ }
13982
+ lastSeparatorPos = separator;
13983
+ node.render(code, options);
13984
+ }
13985
+ if (lastSeparatorPos) {
13986
+ code.remove(lastSeparatorPos, this.end - 1);
13987
+ }
13988
+ }
13278
13989
  }
13279
- applyDeoptimizations() { }
13280
13990
  getObjectEntity() {
13281
13991
  if (this.objectEntity !== null) {
13282
13992
  return this.objectEntity;
@@ -13305,6 +14015,7 @@ class ObjectExpression extends NodeBase {
13305
14015
  ? property.key.name
13306
14016
  : String(property.key.value);
13307
14017
  if (key === '__proto__' && property.kind === 'init') {
14018
+ this.protoProp = property;
13308
14019
  prototype =
13309
14020
  property.value instanceof Literal && property.value.value === null
13310
14021
  ? null
@@ -13317,6 +14028,7 @@ class ObjectExpression extends NodeBase {
13317
14028
  return (this.objectEntity = new ObjectEntity(properties, prototype));
13318
14029
  }
13319
14030
  }
14031
+ ObjectExpression.prototype.applyDeoptimizations = doNotDeoptimize;
13320
14032
 
13321
14033
  class PanicError extends NodeBase {
13322
14034
  initialise() {
@@ -13343,6 +14055,7 @@ class ParseError extends NodeBase {
13343
14055
 
13344
14056
  class PrivateIdentifier extends NodeBase {
13345
14057
  }
14058
+ PrivateIdentifier.prototype.includeNode = onlyIncludeSelf;
13346
14059
 
13347
14060
  class Program extends NodeBase {
13348
14061
  constructor() {
@@ -13410,14 +14123,11 @@ class Program extends NodeBase {
13410
14123
  super.render(code, options);
13411
14124
  }
13412
14125
  }
13413
- applyDeoptimizations() { }
13414
14126
  }
14127
+ Program.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
14128
+ Program.prototype.applyDeoptimizations = doNotDeoptimize;
13415
14129
 
13416
14130
  class Property extends MethodBase {
13417
- constructor() {
13418
- super(...arguments);
13419
- this.declarationInit = null;
13420
- }
13421
14131
  //declare method: boolean;
13422
14132
  get method() {
13423
14133
  return isFlagSet(this.flags, 262144 /* Flag.method */);
@@ -13432,17 +14142,41 @@ class Property extends MethodBase {
13432
14142
  set shorthand(value) {
13433
14143
  this.flags = setFlag(this.flags, 524288 /* Flag.shorthand */, value);
13434
14144
  }
13435
- declare(kind, init) {
13436
- this.declarationInit = init;
13437
- return this.value.declare(kind, UNKNOWN_EXPRESSION);
14145
+ declare(kind, destructuredInitPath, init) {
14146
+ return this.value.declare(kind, this.getPathInProperty(destructuredInitPath), init);
14147
+ }
14148
+ deoptimizeAssignment(destructuredInitPath, init) {
14149
+ this.value.deoptimizeAssignment?.(this.getPathInProperty(destructuredInitPath), init);
13438
14150
  }
13439
14151
  hasEffects(context) {
13440
- if (!this.deoptimized)
13441
- this.applyDeoptimizations();
13442
- const propertyReadSideEffects = this.scope.context.options.treeshake.propertyReadSideEffects;
13443
- return ((this.parent.type === 'ObjectPattern' && propertyReadSideEffects === 'always') ||
13444
- this.key.hasEffects(context) ||
13445
- this.value.hasEffects(context));
14152
+ return this.key.hasEffects(context) || this.value.hasEffects(context);
14153
+ }
14154
+ hasEffectsWhenDestructuring(context, destructuredInitPath, init) {
14155
+ return this.value.hasEffectsWhenDestructuring?.(context, this.getPathInProperty(destructuredInitPath), init);
14156
+ }
14157
+ includeDestructuredIfNecessary(context, destructuredInitPath, init) {
14158
+ const path = this.getPathInProperty(destructuredInitPath);
14159
+ let included = this.value.includeDestructuredIfNecessary(context, path, init) ||
14160
+ this.included;
14161
+ if ((included ||= this.key.hasEffects(createHasEffectsContext()))) {
14162
+ this.key.include(context, false);
14163
+ if (!this.value.included) {
14164
+ this.value.included = true;
14165
+ // Unfortunately, we need to include the value again now, so that any
14166
+ // declared variables are properly included.
14167
+ this.value.includeDestructuredIfNecessary(context, path, init);
14168
+ }
14169
+ }
14170
+ return (this.included = included);
14171
+ }
14172
+ include(context, includeChildrenRecursively) {
14173
+ this.included = true;
14174
+ this.key.include(context, includeChildrenRecursively);
14175
+ this.value.include(context, includeChildrenRecursively);
14176
+ }
14177
+ includePath(path, context) {
14178
+ this.included = true;
14179
+ this.value.includePath(path, context);
13446
14180
  }
13447
14181
  markDeclarationReached() {
13448
14182
  this.value.markDeclarationReached();
@@ -13453,14 +14187,20 @@ class Property extends MethodBase {
13453
14187
  }
13454
14188
  this.value.render(code, options, { isShorthandProperty: this.shorthand });
13455
14189
  }
13456
- applyDeoptimizations() {
13457
- this.deoptimized = true;
13458
- if (this.declarationInit !== null) {
13459
- this.declarationInit.deoptimizePath([UnknownKey, UnknownKey]);
13460
- this.scope.context.requestTreeshakingPass();
13461
- }
14190
+ getPathInProperty(destructuredInitPath) {
14191
+ return destructuredInitPath.at(-1) === UnknownKey
14192
+ ? destructuredInitPath
14193
+ : // For now, we only consider static paths as we do not know how to
14194
+ // deoptimize the path in the dynamic case.
14195
+ this.computed
14196
+ ? [...destructuredInitPath, UnknownKey]
14197
+ : this.key instanceof Identifier
14198
+ ? [...destructuredInitPath, this.key.name]
14199
+ : [...destructuredInitPath, String(this.key.value)];
13462
14200
  }
13463
14201
  }
14202
+ Property.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
14203
+ Property.prototype.applyDeoptimizations = doNotDeoptimize;
13464
14204
 
13465
14205
  class PropertyDefinition extends NodeBase {
13466
14206
  get computed() {
@@ -13493,8 +14233,15 @@ class PropertyDefinition extends NodeBase {
13493
14233
  hasEffectsOnInteractionAtPath(path, interaction, context) {
13494
14234
  return !this.value || this.value.hasEffectsOnInteractionAtPath(path, interaction, context);
13495
14235
  }
13496
- applyDeoptimizations() { }
14236
+ includeNode(context) {
14237
+ this.included = true;
14238
+ this.value?.includePath(UNKNOWN_PATH, context);
14239
+ for (const decorator of this.decorators) {
14240
+ decorator.includePath(UNKNOWN_PATH, context);
14241
+ }
14242
+ }
13497
14243
  }
14244
+ PropertyDefinition.prototype.applyDeoptimizations = doNotDeoptimize;
13498
14245
 
13499
14246
  class ReturnStatement extends NodeBase {
13500
14247
  hasEffects(context) {
@@ -13504,10 +14251,15 @@ class ReturnStatement extends NodeBase {
13504
14251
  return false;
13505
14252
  }
13506
14253
  include(context, includeChildrenRecursively) {
13507
- this.included = true;
14254
+ if (!this.included)
14255
+ this.includeNode(context);
13508
14256
  this.argument?.include(context, includeChildrenRecursively);
13509
14257
  context.brokenFlow = true;
13510
14258
  }
14259
+ includeNode(context) {
14260
+ this.included = true;
14261
+ this.argument?.includePath(UNKNOWN_PATH, context);
14262
+ }
13511
14263
  initialise() {
13512
14264
  super.initialise();
13513
14265
  this.scope.addReturnExpression(this.argument || UNKNOWN_EXPRESSION);
@@ -13521,6 +14273,7 @@ class ReturnStatement extends NodeBase {
13521
14273
  }
13522
14274
  }
13523
14275
  }
14276
+ ReturnStatement.prototype.applyDeoptimizations = doNotDeoptimize;
13524
14277
 
13525
14278
  class SequenceExpression extends NodeBase {
13526
14279
  deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
@@ -13548,10 +14301,15 @@ class SequenceExpression extends NodeBase {
13548
14301
  for (const expression of this.expressions) {
13549
14302
  if (includeChildrenRecursively ||
13550
14303
  (expression === lastExpression && !(this.parent instanceof ExpressionStatement)) ||
13551
- expression.shouldBeIncluded(context))
14304
+ expression.shouldBeIncluded(context)) {
13552
14305
  expression.include(context, includeChildrenRecursively);
14306
+ }
13553
14307
  }
13554
14308
  }
14309
+ includePath(path, context) {
14310
+ this.included = true;
14311
+ this.expressions[this.expressions.length - 1].includePath(path, context);
14312
+ }
13555
14313
  removeAnnotations(code) {
13556
14314
  this.expressions[0].removeAnnotations(code);
13557
14315
  }
@@ -13586,6 +14344,8 @@ class SequenceExpression extends NodeBase {
13586
14344
  }
13587
14345
  }
13588
14346
  }
14347
+ SequenceExpression.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
14348
+ SequenceExpression.prototype.applyDeoptimizations = doNotDeoptimize;
13589
14349
 
13590
14350
  class Super extends NodeBase {
13591
14351
  bind() {
@@ -13597,11 +14357,15 @@ class Super extends NodeBase {
13597
14357
  deoptimizePath(path) {
13598
14358
  this.variable.deoptimizePath(path);
13599
14359
  }
13600
- include() {
13601
- if (!this.included) {
13602
- this.included = true;
13603
- this.scope.context.includeVariableInModule(this.variable);
13604
- }
14360
+ include(context) {
14361
+ if (!this.included)
14362
+ this.includeNode(context);
14363
+ }
14364
+ includeNode(context) {
14365
+ this.included = true;
14366
+ if (!this.deoptimized)
14367
+ this.applyDeoptimizations();
14368
+ this.scope.context.includeVariableInModule(this.variable, EMPTY_PATH, context);
13605
14369
  }
13606
14370
  }
13607
14371
 
@@ -13642,6 +14406,8 @@ class SwitchCase extends NodeBase {
13642
14406
  }
13643
14407
  }
13644
14408
  SwitchCase.prototype.needsBoundaries = true;
14409
+ SwitchCase.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
14410
+ SwitchCase.prototype.applyDeoptimizations = doNotDeoptimize;
13645
14411
 
13646
14412
  class SwitchStatement extends NodeBase {
13647
14413
  createScope(parentScope) {
@@ -13724,6 +14490,8 @@ class SwitchStatement extends NodeBase {
13724
14490
  }
13725
14491
  }
13726
14492
  }
14493
+ SwitchStatement.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
14494
+ SwitchStatement.prototype.applyDeoptimizations = doNotDeoptimize;
13727
14495
 
13728
14496
  class TaggedTemplateExpression extends CallExpressionBase {
13729
14497
  bind() {
@@ -13747,8 +14515,8 @@ class TaggedTemplateExpression extends CallExpressionBase {
13747
14515
  this.tag.hasEffectsOnInteractionAtPath(EMPTY_PATH, this.interaction, context));
13748
14516
  }
13749
14517
  include(context, includeChildrenRecursively) {
13750
- if (!this.deoptimized)
13751
- this.applyDeoptimizations();
14518
+ if (!this.included)
14519
+ this.includeNode(context);
13752
14520
  if (includeChildrenRecursively) {
13753
14521
  super.include(context, includeChildrenRecursively);
13754
14522
  }
@@ -13757,7 +14525,7 @@ class TaggedTemplateExpression extends CallExpressionBase {
13757
14525
  this.tag.include(context, includeChildrenRecursively);
13758
14526
  this.quasi.include(context, includeChildrenRecursively);
13759
14527
  }
13760
- this.tag.includeCallArguments(context, this.args);
14528
+ this.tag.includeCallArguments(context, this.interaction);
13761
14529
  const [returnExpression] = this.getReturnExpression();
13762
14530
  if (!returnExpression.included) {
13763
14531
  returnExpression.include(context, false);
@@ -13792,6 +14560,7 @@ class TaggedTemplateExpression extends CallExpressionBase {
13792
14560
  return this.returnExpression;
13793
14561
  }
13794
14562
  }
14563
+ TaggedTemplateExpression.prototype.includeNode = onlyIncludeSelf;
13795
14564
 
13796
14565
  class TemplateElement extends NodeBase {
13797
14566
  get tail() {
@@ -13805,15 +14574,13 @@ class TemplateElement extends NodeBase {
13805
14574
  hasEffects() {
13806
14575
  return false;
13807
14576
  }
13808
- include() {
13809
- this.included = true;
13810
- }
13811
14577
  parseNode(esTreeNode) {
13812
14578
  this.value = esTreeNode.value;
13813
14579
  return super.parseNode(esTreeNode);
13814
14580
  }
13815
14581
  render() { }
13816
14582
  }
14583
+ TemplateElement.prototype.includeNode = onlyIncludeSelf;
13817
14584
 
13818
14585
  class TemplateLiteral extends NodeBase {
13819
14586
  deoptimizeArgumentsOnInteractionAtPath() { }
@@ -13838,6 +14605,14 @@ class TemplateLiteral extends NodeBase {
13838
14605
  }
13839
14606
  return true;
13840
14607
  }
14608
+ includeNode(context) {
14609
+ this.included = true;
14610
+ if (!this.deoptimized)
14611
+ this.applyDeoptimizations();
14612
+ for (const node of this.expressions) {
14613
+ node.includePath(UNKNOWN_PATH, context);
14614
+ }
14615
+ }
13841
14616
  render(code, options) {
13842
14617
  code.indentExclusionRanges.push([this.start, this.end]);
13843
14618
  super.render(code, options);
@@ -13847,13 +14622,13 @@ class TemplateLiteral extends NodeBase {
13847
14622
  class ModuleScope extends ChildScope {
13848
14623
  constructor(parent, context) {
13849
14624
  super(parent, context);
13850
- this.variables.set('this', new LocalVariable('this', null, UNDEFINED_EXPRESSION, context, 'other'));
14625
+ this.variables.set('this', new LocalVariable('this', null, UNDEFINED_EXPRESSION, EMPTY_PATH, context, 'other'));
13851
14626
  }
13852
- addDeclaration(identifier, context, init, kind) {
14627
+ addDeclaration(identifier, context, init, destructuredInitPath, kind) {
13853
14628
  if (this.context.module.importDescriptions.has(identifier.name)) {
13854
14629
  context.error(logRedeclarationError(identifier.name), identifier.start);
13855
14630
  }
13856
- return super.addDeclaration(identifier, context, init, kind);
14631
+ return super.addDeclaration(identifier, context, init, destructuredInitPath, kind);
13857
14632
  }
13858
14633
  addExportDefaultDeclaration(name, exportDefaultDeclaration, context) {
13859
14634
  const variable = new ExportDefaultVariable(name, exportDefaultDeclaration, context);
@@ -13898,10 +14673,23 @@ class ThisExpression extends NodeBase {
13898
14673
  }
13899
14674
  return this.variable.hasEffectsOnInteractionAtPath(path, interaction, context);
13900
14675
  }
13901
- include() {
14676
+ include(context) {
14677
+ if (!this.included)
14678
+ this.includeNode(context);
14679
+ }
14680
+ includeNode(context) {
14681
+ this.included = true;
14682
+ if (!this.deoptimized)
14683
+ this.applyDeoptimizations();
14684
+ this.scope.context.includeVariableInModule(this.variable, EMPTY_PATH, context);
14685
+ }
14686
+ includePath(path, context) {
13902
14687
  if (!this.included) {
13903
14688
  this.included = true;
13904
- this.scope.context.includeVariableInModule(this.variable);
14689
+ this.scope.context.includeVariableInModule(this.variable, path, context);
14690
+ }
14691
+ else if (path.length > 0) {
14692
+ this.variable.includePath(path, context);
13905
14693
  }
13906
14694
  }
13907
14695
  initialise() {
@@ -13929,7 +14717,8 @@ class ThrowStatement extends NodeBase {
13929
14717
  return true;
13930
14718
  }
13931
14719
  include(context, includeChildrenRecursively) {
13932
- this.included = true;
14720
+ if (!this.included)
14721
+ this.includeNode(context);
13933
14722
  this.argument.include(context, includeChildrenRecursively);
13934
14723
  context.brokenFlow = true;
13935
14724
  }
@@ -13940,6 +14729,7 @@ class ThrowStatement extends NodeBase {
13940
14729
  }
13941
14730
  }
13942
14731
  }
14732
+ ThrowStatement.prototype.includeNode = onlyIncludeSelf;
13943
14733
 
13944
14734
  class TryStatement extends NodeBase {
13945
14735
  constructor() {
@@ -13976,6 +14766,8 @@ class TryStatement extends NodeBase {
13976
14766
  this.finalizer?.include(context, includeChildrenRecursively);
13977
14767
  }
13978
14768
  }
14769
+ TryStatement.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
14770
+ TryStatement.prototype.applyDeoptimizations = doNotDeoptimize;
13979
14771
 
13980
14772
  const unaryOperators = {
13981
14773
  '!': value => !value,
@@ -14021,6 +14813,7 @@ class UnaryExpression extends NodeBase {
14021
14813
  }
14022
14814
  }
14023
14815
  }
14816
+ UnaryExpression.prototype.includeNode = onlyIncludeSelf;
14024
14817
 
14025
14818
  class UpdateExpression extends NodeBase {
14026
14819
  hasEffects(context) {
@@ -14032,9 +14825,8 @@ class UpdateExpression extends NodeBase {
14032
14825
  return path.length > 1 || type !== INTERACTION_ACCESSED;
14033
14826
  }
14034
14827
  include(context, includeChildrenRecursively) {
14035
- if (!this.deoptimized)
14036
- this.applyDeoptimizations();
14037
- this.included = true;
14828
+ if (!this.included)
14829
+ this.includeNode(context);
14038
14830
  this.argument.includeAsAssignmentTarget(context, includeChildrenRecursively, true);
14039
14831
  }
14040
14832
  initialise() {
@@ -14073,6 +14865,7 @@ class UpdateExpression extends NodeBase {
14073
14865
  this.scope.context.requestTreeshakingPass();
14074
14866
  }
14075
14867
  }
14868
+ UpdateExpression.prototype.includeNode = onlyIncludeSelf;
14076
14869
 
14077
14870
  function areAllDeclarationsIncludedAndNotExported(declarations, exportNamesByVariable) {
14078
14871
  for (const declarator of declarations) {
@@ -14103,8 +14896,9 @@ class VariableDeclaration extends NodeBase {
14103
14896
  include(context, includeChildrenRecursively, { asSingleStatement } = BLANK) {
14104
14897
  this.included = true;
14105
14898
  for (const declarator of this.declarations) {
14106
- if (includeChildrenRecursively || declarator.shouldBeIncluded(context))
14899
+ if (includeChildrenRecursively || declarator.shouldBeIncluded(context)) {
14107
14900
  declarator.include(context, includeChildrenRecursively);
14901
+ }
14108
14902
  const { id, init } = declarator;
14109
14903
  if (asSingleStatement) {
14110
14904
  id.include(context, includeChildrenRecursively);
@@ -14142,7 +14936,6 @@ class VariableDeclaration extends NodeBase {
14142
14936
  this.renderReplacedDeclarations(code, options);
14143
14937
  }
14144
14938
  }
14145
- applyDeoptimizations() { }
14146
14939
  renderDeclarationEnd(code, separatorString, lastSeparatorPos, actualContentEnd, renderedContentEnd, systemPatternExports, options) {
14147
14940
  if (code.original.charCodeAt(this.end - 1) === 59 /*";"*/) {
14148
14941
  code.remove(this.end - 1, this.end);
@@ -14185,8 +14978,7 @@ class VariableDeclaration extends NodeBase {
14185
14978
  const singleSystemExport = gatherSystemExportsAndGetSingleExport(separatedNodes, options, aggregatedSystemExports);
14186
14979
  for (const { node, start, separator, contentEnd, end } of separatedNodes) {
14187
14980
  if (!node.included) {
14188
- code.remove(start, end);
14189
- node.removeAnnotations(code);
14981
+ treeshakeNode(node, code, start, end);
14190
14982
  continue;
14191
14983
  }
14192
14984
  node.render(code, options);
@@ -14256,6 +15048,8 @@ function gatherSystemExportsAndGetSingleExport(separatedNodes, options, aggregat
14256
15048
  }
14257
15049
  return singleSystemExport;
14258
15050
  }
15051
+ VariableDeclaration.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
15052
+ VariableDeclaration.prototype.applyDeoptimizations = doNotDeoptimize;
14259
15053
 
14260
15054
  class WhileStatement extends NodeBase {
14261
15055
  hasEffects(context) {
@@ -14269,13 +15063,25 @@ class WhileStatement extends NodeBase {
14269
15063
  includeLoopBody(context, this.body, includeChildrenRecursively);
14270
15064
  }
14271
15065
  }
15066
+ WhileStatement.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
15067
+ WhileStatement.prototype.applyDeoptimizations = doNotDeoptimize;
14272
15068
 
14273
15069
  class YieldExpression extends NodeBase {
15070
+ applyDeoptimizations() {
15071
+ this.deoptimized = true;
15072
+ this.argument?.deoptimizePath(UNKNOWN_PATH);
15073
+ }
14274
15074
  hasEffects(context) {
14275
15075
  if (!this.deoptimized)
14276
15076
  this.applyDeoptimizations();
14277
15077
  return !(context.ignore.returnYield && !this.argument?.hasEffects(context));
14278
15078
  }
15079
+ includeNode(context) {
15080
+ this.included = true;
15081
+ if (!this.deoptimized)
15082
+ this.applyDeoptimizations();
15083
+ this.argument?.includePath(UNKNOWN_PATH, context);
15084
+ }
14279
15085
  render(code, options) {
14280
15086
  if (this.argument) {
14281
15087
  this.argument.render(code, options, { preventASI: true });
@@ -14509,7 +15315,7 @@ const bufferParsers = [
14509
15315
  const annotations = (node.annotations = convertAnnotations(buffer[position + 1], buffer));
14510
15316
  node.annotationNoSideEffects = annotations.some(comment => comment.type === 'noSideEffects');
14511
15317
  const parameters = (node.params = convertNodeList(node, scope, buffer[position + 2], buffer));
14512
- scope.addParameterVariables(parameters.map(parameter => parameter.declare('parameter', UNKNOWN_EXPRESSION)), parameters[parameters.length - 1] instanceof RestElement);
15318
+ scope.addParameterVariables(parameters.map(parameter => parameter.declare('parameter', EMPTY_PATH, UNKNOWN_EXPRESSION)), parameters[parameters.length - 1] instanceof RestElement);
14513
15319
  node.body = convertNode(node, scope.bodyScope, buffer[position + 3], buffer);
14514
15320
  },
14515
15321
  function assignmentExpression(node, position, buffer) {
@@ -14555,7 +15361,7 @@ const bufferParsers = [
14555
15361
  const parameterPosition = buffer[position];
14556
15362
  const parameter = (node.param =
14557
15363
  parameterPosition === 0 ? null : convertNode(node, scope, parameterPosition, buffer));
14558
- parameter?.declare('parameter', UNKNOWN_EXPRESSION);
15364
+ parameter?.declare('parameter', EMPTY_PATH, UNKNOWN_EXPRESSION);
14559
15365
  node.body = convertNode(node, scope.bodyScope, buffer[position + 1], buffer);
14560
15366
  },
14561
15367
  function chainExpression(node, position, buffer) {
@@ -14693,7 +15499,7 @@ const bufferParsers = [
14693
15499
  node.id =
14694
15500
  idPosition === 0 ? null : convertNode(node, scope.parent, idPosition, buffer);
14695
15501
  const parameters = (node.params = convertNodeList(node, scope, buffer[position + 3], buffer));
14696
- scope.addParameterVariables(parameters.map(parameter => parameter.declare('parameter', UNKNOWN_EXPRESSION)), parameters[parameters.length - 1] instanceof RestElement);
15502
+ scope.addParameterVariables(parameters.map(parameter => parameter.declare('parameter', EMPTY_PATH, UNKNOWN_EXPRESSION)), parameters[parameters.length - 1] instanceof RestElement);
14697
15503
  node.body = convertNode(node, scope.bodyScope, buffer[position + 4], buffer);
14698
15504
  },
14699
15505
  function functionExpression(node, position, buffer) {
@@ -14706,7 +15512,7 @@ const bufferParsers = [
14706
15512
  const idPosition = buffer[position + 2];
14707
15513
  node.id = idPosition === 0 ? null : convertNode(node, node.idScope, idPosition, buffer);
14708
15514
  const parameters = (node.params = convertNodeList(node, scope, buffer[position + 3], buffer));
14709
- scope.addParameterVariables(parameters.map(parameter => parameter.declare('parameter', UNKNOWN_EXPRESSION)), parameters[parameters.length - 1] instanceof RestElement);
15515
+ scope.addParameterVariables(parameters.map(parameter => parameter.declare('parameter', EMPTY_PATH, UNKNOWN_EXPRESSION)), parameters[parameters.length - 1] instanceof RestElement);
14710
15516
  node.body = convertNode(node, scope.bodyScope, buffer[position + 4], buffer);
14711
15517
  },
14712
15518
  function identifier(node, position, buffer) {
@@ -15170,8 +15976,8 @@ class ExportShimVariable extends Variable {
15170
15976
  super(MISSING_EXPORT_SHIM_VARIABLE);
15171
15977
  this.module = module;
15172
15978
  }
15173
- include() {
15174
- super.include();
15979
+ includePath(path, context) {
15980
+ super.includePath(path, context);
15175
15981
  this.module.needsExportShim = true;
15176
15982
  }
15177
15983
  }
@@ -15869,16 +16675,15 @@ class Module {
15869
16675
  markModuleAndImpureDependenciesAsExecuted(this);
15870
16676
  this.graph.needsTreeshakingPass = true;
15871
16677
  }
16678
+ const inclusionContext = createInclusionContext();
15872
16679
  for (const exportName of this.exports.keys()) {
15873
16680
  if (includeNamespaceMembers || exportName !== this.info.syntheticNamedExports) {
15874
16681
  const variable = this.getVariableForExportName(exportName)[0];
15875
16682
  if (!variable) {
15876
16683
  return error(logMissingEntryExport(exportName, this.id));
15877
16684
  }
16685
+ this.includeVariable(variable, UNKNOWN_PATH, inclusionContext);
15878
16686
  variable.deoptimizePath(UNKNOWN_PATH);
15879
- if (!variable.included) {
15880
- this.includeVariable(variable);
15881
- }
15882
16687
  }
15883
16688
  }
15884
16689
  for (const name of this.getReexports()) {
@@ -15886,7 +16691,7 @@ class Module {
15886
16691
  if (variable) {
15887
16692
  variable.deoptimizePath(UNKNOWN_PATH);
15888
16693
  if (!variable.included) {
15889
- this.includeVariable(variable);
16694
+ this.includeVariable(variable, UNKNOWN_PATH, inclusionContext);
15890
16695
  }
15891
16696
  if (variable instanceof ExternalVariable) {
15892
16697
  variable.module.reexported = true;
@@ -15907,13 +16712,12 @@ class Module {
15907
16712
  this.graph.needsTreeshakingPass = true;
15908
16713
  }
15909
16714
  let includeNamespaceMembers = false;
16715
+ const inclusionContext = createInclusionContext();
15910
16716
  for (const name of names) {
15911
16717
  const variable = this.getVariableForExportName(name)[0];
15912
16718
  if (variable) {
15913
16719
  variable.deoptimizePath(UNKNOWN_PATH);
15914
- if (!variable.included) {
15915
- this.includeVariable(variable);
15916
- }
16720
+ this.includeVariable(variable, UNKNOWN_PATH, inclusionContext);
15917
16721
  }
15918
16722
  if (!this.exports.has(name) && !this.reexportDescriptions.has(name)) {
15919
16723
  includeNamespaceMembers = true;
@@ -16014,6 +16818,7 @@ class Module {
16014
16818
  manualPureFunctions: this.graph.pureFunctions,
16015
16819
  module: this,
16016
16820
  moduleContext: this.context,
16821
+ newlyIncludedVariableInits: this.graph.newlyIncludedVariableInits,
16017
16822
  options: this.options,
16018
16823
  requestTreeshakingPass: () => (this.graph.needsTreeshakingPass = true),
16019
16824
  traceExport: (name) => this.getVariableForExportName(name)[0],
@@ -16354,13 +17159,13 @@ class Module {
16354
17159
  for (const module of [this, ...this.exportAllModules]) {
16355
17160
  if (module instanceof ExternalModule) {
16356
17161
  const [externalVariable] = module.getVariableForExportName('*');
16357
- externalVariable.include();
17162
+ externalVariable.includePath(UNKNOWN_PATH, createInclusionContext());
16358
17163
  this.includedImports.add(externalVariable);
16359
17164
  externalNamespaces.add(externalVariable);
16360
17165
  }
16361
17166
  else if (module.info.syntheticNamedExports) {
16362
17167
  const syntheticNamespace = module.getSyntheticNamespace();
16363
- syntheticNamespace.include();
17168
+ syntheticNamespace.includePath(UNKNOWN_PATH, createInclusionContext());
16364
17169
  this.includedImports.add(syntheticNamespace);
16365
17170
  syntheticNamespaces.add(syntheticNamespace);
16366
17171
  }
@@ -16370,7 +17175,9 @@ class Module {
16370
17175
  includeDynamicImport(node) {
16371
17176
  const resolution = this.dynamicImports.find(dynamicImport => dynamicImport.node === node).resolution;
16372
17177
  if (resolution instanceof Module) {
16373
- resolution.includedDynamicImporters.push(this);
17178
+ if (!resolution.includedDynamicImporters.includes(this)) {
17179
+ resolution.includedDynamicImporters.push(this);
17180
+ }
16374
17181
  const importedNames = this.options.treeshake
16375
17182
  ? node.getDeterministicImportedNames()
16376
17183
  : undefined;
@@ -16382,15 +17189,15 @@ class Module {
16382
17189
  }
16383
17190
  }
16384
17191
  }
16385
- includeVariable(variable) {
16386
- const variableModule = variable.module;
16387
- if (variable.included) {
17192
+ includeVariable(variable, path, context) {
17193
+ const { included, module: variableModule } = variable;
17194
+ variable.includePath(path, context);
17195
+ if (included) {
16388
17196
  if (variableModule instanceof Module && variableModule !== this) {
16389
17197
  getAndExtendSideEffectModules(variable, this);
16390
17198
  }
16391
17199
  }
16392
17200
  else {
16393
- variable.include();
16394
17201
  this.graph.needsTreeshakingPass = true;
16395
17202
  if (variableModule instanceof Module) {
16396
17203
  if (!variableModule.isExecuted) {
@@ -16407,8 +17214,8 @@ class Module {
16407
17214
  }
16408
17215
  }
16409
17216
  }
16410
- includeVariableInModule(variable) {
16411
- this.includeVariable(variable);
17217
+ includeVariableInModule(variable, path, context) {
17218
+ this.includeVariable(variable, path, context);
16412
17219
  const variableModule = variable.module;
16413
17220
  if (variableModule && variableModule !== this) {
16414
17221
  this.includedImports.add(variable);
@@ -21005,10 +21812,11 @@ class Graph {
21005
21812
  this.options = options;
21006
21813
  this.astLru = flru(5);
21007
21814
  this.cachedModules = new Map();
21008
- this.deoptimizationTracker = new PathTracker();
21815
+ this.deoptimizationTracker = new EntityPathTracker();
21009
21816
  this.entryModules = [];
21010
21817
  this.modulesById = new Map();
21011
21818
  this.needsTreeshakingPass = false;
21819
+ this.newlyIncludedVariableInits = new Set();
21012
21820
  this.phase = BuildPhase.LOAD_AND_PARSE;
21013
21821
  this.scope = new GlobalScope();
21014
21822
  this.watchFiles = Object.create(null);
@@ -21102,6 +21910,7 @@ class Graph {
21102
21910
  }
21103
21911
  if (this.options.treeshake) {
21104
21912
  let treeshakingPass = 1;
21913
+ this.newlyIncludedVariableInits.clear();
21105
21914
  do {
21106
21915
  timeStart(`treeshaking pass ${treeshakingPass}`, 3);
21107
21916
  this.needsTreeshakingPass = false;
@@ -21126,6 +21935,10 @@ class Graph {
21126
21935
  }
21127
21936
  }
21128
21937
  }
21938
+ for (const entity of this.newlyIncludedVariableInits) {
21939
+ this.newlyIncludedVariableInits.delete(entity);
21940
+ entity.include(createInclusionContext(), false);
21941
+ }
21129
21942
  timeEnd(`treeshaking pass ${treeshakingPass++}`, 3);
21130
21943
  } while (this.needsTreeshakingPass);
21131
21944
  }
@@ -22005,7 +22818,7 @@ createColors();
22005
22818
 
22006
22819
  // @see https://no-color.org
22007
22820
  // @see https://www.npmjs.com/package/chalk
22008
- const { bold, cyan, dim, gray, green, red, underline, yellow } = createColors({
22821
+ const { bold, cyan, dim, red} = createColors({
22009
22822
  useColor: env$1.FORCE_COLOR !== '0' && !env$1.NO_COLOR
22010
22823
  });
22011
22824