@rollup/wasm-node 4.16.3 → 4.17.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,13 +1,13 @@
1
1
  /*
2
2
  @license
3
- Rollup.js v4.16.3
4
- Tue, 23 Apr 2024 05:12:04 GMT - commit b9a62fd4cf28538d7c3b268eb25e709b45d44cce
3
+ Rollup.js v4.17.0
4
+ Sat, 27 Apr 2024 11:29:22 GMT - commit 91352494fc722bcd5e8e922cd1497b34aec57a67
5
5
 
6
6
  https://github.com/rollup/rollup
7
7
 
8
8
  Released under the MIT License.
9
9
  */
10
- import { normalize, getImportPath, ExportDefaultDeclaration as ExportDefaultDeclaration$1, CallExpression as CallExpression$1, EMPTY_ARRAY, LOGLEVEL_WARN, logUnusedExternalImports, ANNOTATION_KEY, INVALID_ANNOTATION_KEY, Program as Program$1, logRedeclarationError, CatchClause as CatchClause$1, logDuplicateArgumentNameError, BLANK, logIllegalImportReassignment, logModuleLevelDirective, ReturnStatement as ReturnStatement$1, VariableDeclarator as VariableDeclarator$1, Property as Property$1, logConstVariableReassignError, ExpressionStatement as ExpressionStatement$1, ArrowFunctionExpression as ArrowFunctionExpression$1, logMissingExport, EMPTY_SET, logCannotCallNamespace, logEval, BlockStatement as BlockStatement$1, getRollupError, logParseError, logModuleParseError, error, LOGLEVEL_INFO, logFirstSideEffect, locate, logInvalidAnnotation, Identifier as Identifier$1, logThisIsUndefined, getReadStringFunction, convertString, convertAnnotations, FIXED_STRINGS, convertNode as convertNode$1, EMPTY_OBJECT, logImportAttributeIsInvalid, logImportOptionsAreInvalid, logSyntheticNamedExportsNeedNamespaceExport, logMissingEntryExport, logInvalidFormatForTopLevelAwait, logDuplicateExportError, logInvalidSourcemapForError, augmentCodeLocation, logInconsistentImportAttributes, logNamespaceConflict, logAmbiguousExternalNamespaces, logShimmedExport, parseAst, logCircularReexport, TemplateLiteral as TemplateLiteral$1, Literal as Literal$1, logMissingNodeBuiltins, logIllegalIdentifierAsName, logMissingNameOptionForIifeExport, logMissingNameOptionForUmdExport, 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, LOGLEVEL_ERROR, logLevelPriority, LOGLEVEL_DEBUG, logUnknownOption, printQuotedStringList, logInvalidSetAssetSourceCall, logPluginError, logNoTransformMapOrAstWithoutCode, relativeId, logBadLoader, logExternalModulesCannotBeTransformedToModules, logInternalIdCannotBeExternal, isRelative, logUnresolvedImport, logUnresolvedImportTreatedAsExternal, logExternalSyntheticExports, logUnresolvedEntry, logUnresolvedImplicitDependant, logExternalModulesCannotBeIncludedInManualChunks, logEntryCannotBeExternal, logImplicitDependantCannotBeExternal, logNoAssetSourceSet, logFileReferenceIdNotFoundForFilename, logAssetReferenceIdNotFoundForSetSource, logAssetSourceAlreadySet, logInvalidRollupPhaseForChunkEmission, logFileNameConflict, logAssetNotFinalisedForFileName, logChunkNotGeneratedForFileName, logInvalidLogPosition, logInputHookInOutputPlugin, logInvalidFunctionPluginHook, logInvalidAddonPluginHook, logImplicitDependantIsNotIncluded, logCircularDependency, augmentLogMessage, URL_TREESHAKE_MODULESIDEEFFECTS, URL_TREESHAKE, URL_OUTPUT_INLINEDYNAMICIMPORTS, URL_PRESERVEENTRYSIGNATURES, URL_OUTPUT_AMD_BASEPATH, logInvalidExportOptionValue, warnDeprecation, URL_OUTPUT_INTEROP, URL_OUTPUT_MANUALCHUNKS, isValidUrl, addTrailingSlashIfMissed, URL_OUTPUT_SOURCEMAPBASEURL, URL_OUTPUT_GENERATEDCODE, URL_OUTPUT_EXTERNALIMPORTATTRIBUTES, logAlreadyClosed, logMissingFileOrDirOption, logCannotEmitFromOptionsHook, URL_WATCH } from './parseAst.js';
10
+ import { normalize, getImportPath, ExportDefaultDeclaration as ExportDefaultDeclaration$1, CallExpression as CallExpression$1, EMPTY_ARRAY, LOGLEVEL_WARN, logUnusedExternalImports, ANNOTATION_KEY, INVALID_ANNOTATION_KEY, Program as Program$1, BLANK, logIllegalImportReassignment, logRedeclarationError, CatchClause as CatchClause$1, logDuplicateArgumentNameError, logModuleLevelDirective, ReturnStatement as ReturnStatement$1, VariableDeclarator as VariableDeclarator$1, Property as Property$1, logConstVariableReassignError, ExpressionStatement as ExpressionStatement$1, ArrowFunctionExpression as ArrowFunctionExpression$1, logMissingExport, EMPTY_SET, logCannotCallNamespace, logEval, BlockStatement as BlockStatement$1, getRollupError, logParseError, logModuleParseError, error, LOGLEVEL_INFO, logFirstSideEffect, locate, logInvalidAnnotation, Identifier as Identifier$1, logThisIsUndefined, getReadStringFunction, convertString, convertAnnotations, FIXED_STRINGS, convertNode as convertNode$1, EMPTY_OBJECT, logImportAttributeIsInvalid, logImportOptionsAreInvalid, logSyntheticNamedExportsNeedNamespaceExport, logMissingEntryExport, logInvalidFormatForTopLevelAwait, logDuplicateExportError, logInvalidSourcemapForError, augmentCodeLocation, logInconsistentImportAttributes, logNamespaceConflict, logAmbiguousExternalNamespaces, logShimmedExport, parseAst, logCircularReexport, TemplateLiteral as TemplateLiteral$1, Literal as Literal$1, logMissingNodeBuiltins, logIllegalIdentifierAsName, logMissingNameOptionForIifeExport, logMissingNameOptionForUmdExport, 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, LOGLEVEL_ERROR, logLevelPriority, LOGLEVEL_DEBUG, logUnknownOption, printQuotedStringList, logInvalidSetAssetSourceCall, logPluginError, logNoTransformMapOrAstWithoutCode, relativeId, logBadLoader, logExternalModulesCannotBeTransformedToModules, logInternalIdCannotBeExternal, isRelative, logUnresolvedImport, logUnresolvedImportTreatedAsExternal, logExternalSyntheticExports, logUnresolvedEntry, logUnresolvedImplicitDependant, logExternalModulesCannotBeIncludedInManualChunks, logEntryCannotBeExternal, logImplicitDependantCannotBeExternal, logNoAssetSourceSet, logFileReferenceIdNotFoundForFilename, logAssetReferenceIdNotFoundForSetSource, logAssetSourceAlreadySet, logInvalidRollupPhaseForChunkEmission, logFileNameConflict, logAssetNotFinalisedForFileName, logChunkNotGeneratedForFileName, logInvalidLogPosition, logInputHookInOutputPlugin, logInvalidFunctionPluginHook, logInvalidAddonPluginHook, logImplicitDependantIsNotIncluded, logCircularDependency, augmentLogMessage, URL_TREESHAKE_MODULESIDEEFFECTS, URL_TREESHAKE, URL_OUTPUT_INLINEDYNAMICIMPORTS, URL_PRESERVEENTRYSIGNATURES, URL_OUTPUT_AMD_BASEPATH, logInvalidExportOptionValue, warnDeprecation, URL_OUTPUT_INTEROP, URL_OUTPUT_MANUALCHUNKS, isValidUrl, addTrailingSlashIfMissed, URL_OUTPUT_SOURCEMAPBASEURL, URL_OUTPUT_GENERATEDCODE, 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
12
  import require$$0$1, { win32, posix, isAbsolute, resolve } from 'path';
13
13
  import { parseAsync, xxhashBase64Url, xxhashBase36, xxhashBase16 } from '../../native.js';
@@ -16,7 +16,7 @@ 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.16.3";
19
+ var version = "4.17.0";
20
20
 
21
21
  const comma = ','.charCodeAt(0);
22
22
  const semicolon = ';'.charCodeAt(0);
@@ -1960,7 +1960,6 @@ class Variable extends ExpressionEntity {
1960
1960
  addReference(_identifier) { }
1961
1961
  /**
1962
1962
  * Check if the identifier variable is only used as function call
1963
- * Forward the check to the export default variable if it is only used once
1964
1963
  * @returns true if the variable is only used as function call
1965
1964
  */
1966
1965
  getOnlyFunctionCallUsed() {
@@ -5677,950 +5676,340 @@ class ArrayPattern extends NodeBase {
5677
5676
  }
5678
5677
  }
5679
5678
 
5680
- class LocalVariable extends Variable {
5681
- constructor(name, declarator, init, context, kind) {
5682
- super(name);
5683
- this.init = init;
5684
- this.calledFromTryStatement = false;
5685
- this.additionalInitializers = null;
5686
- this.expressionsToBeDeoptimized = [];
5687
- this.declarations = declarator ? [declarator] : [];
5688
- this.deoptimizationTracker = context.deoptimizationTracker;
5689
- this.module = context.module;
5690
- this.kind = kind;
5691
- }
5692
- addDeclaration(identifier, init) {
5693
- this.declarations.push(identifier);
5694
- this.markInitializersForDeoptimization().push(init);
5695
- }
5696
- consolidateInitializers() {
5697
- if (this.additionalInitializers) {
5698
- for (const initializer of this.additionalInitializers) {
5699
- initializer.deoptimizePath(UNKNOWN_PATH);
5700
- }
5701
- this.additionalInitializers = null;
5702
- }
5703
- }
5704
- deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
5705
- if (this.isReassigned) {
5706
- deoptimizeInteraction(interaction);
5707
- return;
5708
- }
5709
- recursionTracker.withTrackedEntityAtPath(path, this.init, () => this.init.deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker), undefined);
5710
- }
5711
- deoptimizePath(path) {
5712
- if (this.isReassigned ||
5713
- this.deoptimizationTracker.trackEntityAtPathAndGetIfTracked(path, this)) {
5714
- return;
5715
- }
5716
- if (path.length === 0) {
5717
- this.markReassigned();
5718
- const expressionsToBeDeoptimized = this.expressionsToBeDeoptimized;
5719
- this.expressionsToBeDeoptimized = EMPTY_ARRAY;
5720
- for (const expression of expressionsToBeDeoptimized) {
5721
- expression.deoptimizeCache();
5722
- }
5723
- this.init.deoptimizePath(UNKNOWN_PATH);
5724
- }
5725
- else {
5726
- this.init.deoptimizePath(path);
5727
- }
5728
- }
5729
- getLiteralValueAtPath(path, recursionTracker, origin) {
5730
- if (this.isReassigned) {
5731
- return UnknownValue;
5732
- }
5733
- return recursionTracker.withTrackedEntityAtPath(path, this.init, () => {
5734
- this.expressionsToBeDeoptimized.push(origin);
5735
- return this.init.getLiteralValueAtPath(path, recursionTracker, origin);
5736
- }, UnknownValue);
5737
- }
5738
- getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin) {
5739
- if (this.isReassigned) {
5740
- return UNKNOWN_RETURN_EXPRESSION;
5741
- }
5742
- return recursionTracker.withTrackedEntityAtPath(path, this.init, () => {
5743
- this.expressionsToBeDeoptimized.push(origin);
5744
- return this.init.getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin);
5745
- }, UNKNOWN_RETURN_EXPRESSION);
5746
- }
5747
- hasEffectsOnInteractionAtPath(path, interaction, context) {
5748
- switch (interaction.type) {
5749
- case INTERACTION_ACCESSED: {
5750
- if (this.isReassigned)
5751
- return true;
5752
- return (!context.accessed.trackEntityAtPathAndGetIfTracked(path, this) &&
5753
- this.init.hasEffectsOnInteractionAtPath(path, interaction, context));
5754
- }
5755
- case INTERACTION_ASSIGNED: {
5756
- if (this.included)
5757
- return true;
5758
- if (path.length === 0)
5759
- return false;
5760
- if (this.isReassigned)
5761
- return true;
5762
- return (!context.assigned.trackEntityAtPathAndGetIfTracked(path, this) &&
5763
- this.init.hasEffectsOnInteractionAtPath(path, interaction, context));
5764
- }
5765
- case INTERACTION_CALLED: {
5766
- if (this.isReassigned)
5767
- return true;
5768
- return (!(interaction.withNew ? context.instantiated : context.called).trackEntityAtPathAndGetIfTracked(path, interaction.args, this) &&
5769
- this.init.hasEffectsOnInteractionAtPath(path, interaction, context));
5770
- }
5771
- }
5772
- }
5773
- include() {
5774
- if (!this.included) {
5775
- super.include();
5776
- for (const declaration of this.declarations) {
5777
- // If node is a default export, it can save a tree-shaking run to include the full declaration now
5778
- if (!declaration.included)
5779
- declaration.include(createInclusionContext(), false);
5780
- let node = declaration.parent;
5781
- while (!node.included) {
5782
- // We do not want to properly include parents in case they are part of a dead branch
5783
- // in which case .include() might pull in more dead code
5784
- node.included = true;
5785
- if (node.type === Program$1)
5786
- break;
5787
- node = node.parent;
5788
- }
5789
- }
5679
+ /** @typedef { import('estree').Node} Node */
5680
+ /** @typedef {Node | {
5681
+ * type: 'PropertyDefinition';
5682
+ * computed: boolean;
5683
+ * value: Node
5684
+ * }} NodeWithPropertyDefinition */
5685
+
5686
+ /**
5687
+ *
5688
+ * @param {NodeWithPropertyDefinition} node
5689
+ * @param {NodeWithPropertyDefinition} parent
5690
+ * @returns {boolean}
5691
+ */
5692
+ function is_reference (node, parent) {
5693
+ if (node.type === 'MemberExpression') {
5694
+ return !node.computed && is_reference(node.object, node);
5695
+ }
5696
+
5697
+ if (node.type === 'Identifier') {
5698
+ if (!parent) return true;
5699
+
5700
+ switch (parent.type) {
5701
+ // disregard `bar` in `foo.bar`
5702
+ case 'MemberExpression': return parent.computed || node === parent.object;
5703
+
5704
+ // disregard the `foo` in `class {foo(){}}` but keep it in `class {[foo](){}}`
5705
+ case 'MethodDefinition': return parent.computed;
5706
+
5707
+ // disregard the `foo` in `class {foo=bar}` but keep it in `class {[foo]=bar}` and `class {bar=foo}`
5708
+ case 'PropertyDefinition': return parent.computed || node === parent.value;
5709
+
5710
+ // disregard the `bar` in `{ bar: foo }`, but keep it in `{ [bar]: foo }`
5711
+ case 'Property': return parent.computed || node === parent.value;
5712
+
5713
+ // disregard the `bar` in `export { foo as bar }` or
5714
+ // the foo in `import { foo as bar }`
5715
+ case 'ExportSpecifier':
5716
+ case 'ImportSpecifier': return node === parent.local;
5717
+
5718
+ // disregard the `foo` in `foo: while (...) { ... break foo; ... continue foo;}`
5719
+ case 'LabeledStatement':
5720
+ case 'BreakStatement':
5721
+ case 'ContinueStatement': return false;
5722
+ default: return true;
5723
+ }
5724
+ }
5725
+
5726
+ return false;
5727
+ }
5728
+
5729
+ const PureFunctionKey = Symbol('PureFunction');
5730
+ const getPureFunctions = ({ treeshake }) => {
5731
+ const pureFunctions = Object.create(null);
5732
+ for (const functionName of treeshake ? treeshake.manualPureFunctions : []) {
5733
+ let currentFunctions = pureFunctions;
5734
+ for (const pathSegment of functionName.split('.')) {
5735
+ currentFunctions = currentFunctions[pathSegment] ||= Object.create(null);
5790
5736
  }
5737
+ currentFunctions[PureFunctionKey] = true;
5791
5738
  }
5792
- includeCallArguments(context, parameters) {
5793
- if (this.isReassigned || context.includedCallArguments.has(this.init)) {
5794
- for (const argument of parameters) {
5795
- argument.include(context, false);
5796
- }
5797
- }
5798
- else {
5799
- context.includedCallArguments.add(this.init);
5800
- this.init.includeCallArguments(context, parameters);
5801
- context.includedCallArguments.delete(this.init);
5802
- }
5739
+ return pureFunctions;
5740
+ };
5741
+
5742
+ const doNothing = () => { };
5743
+
5744
+ /* eslint sort-keys: "off" */
5745
+ const ValueProperties = Symbol('Value Properties');
5746
+ const getTruthyLiteralValue = () => UnknownTruthyValue;
5747
+ const returnFalse = () => false;
5748
+ const returnTrue = () => true;
5749
+ const PURE = {
5750
+ deoptimizeArgumentsOnCall: doNothing,
5751
+ getLiteralValue: getTruthyLiteralValue,
5752
+ hasEffectsWhenCalled: returnFalse
5753
+ };
5754
+ const IMPURE = {
5755
+ deoptimizeArgumentsOnCall: doNothing,
5756
+ getLiteralValue: getTruthyLiteralValue,
5757
+ hasEffectsWhenCalled: returnTrue
5758
+ };
5759
+ const PURE_WITH_ARRAY = {
5760
+ deoptimizeArgumentsOnCall: doNothing,
5761
+ getLiteralValue: getTruthyLiteralValue,
5762
+ hasEffectsWhenCalled({ args }) {
5763
+ return args.length > 1 && !(args[1] instanceof ArrayExpression);
5803
5764
  }
5804
- markCalledFromTryStatement() {
5805
- this.calledFromTryStatement = true;
5765
+ };
5766
+ const GETTER_ACCESS = {
5767
+ deoptimizeArgumentsOnCall: doNothing,
5768
+ getLiteralValue: getTruthyLiteralValue,
5769
+ hasEffectsWhenCalled({ args }, context) {
5770
+ const [_thisArgument, firstArgument] = args;
5771
+ return (!(firstArgument instanceof ExpressionEntity) ||
5772
+ firstArgument.hasEffectsOnInteractionAtPath(UNKNOWN_PATH, NODE_INTERACTION_UNKNOWN_ACCESS, context));
5806
5773
  }
5807
- markInitializersForDeoptimization() {
5808
- if (this.additionalInitializers === null) {
5809
- this.additionalInitializers = [this.init];
5810
- this.init = UNKNOWN_EXPRESSION;
5811
- this.markReassigned();
5774
+ };
5775
+ // We use shortened variables to reduce file size here
5776
+ /* OBJECT */
5777
+ const O = {
5778
+ __proto__: null,
5779
+ [ValueProperties]: IMPURE
5780
+ };
5781
+ /* PURE FUNCTION */
5782
+ const PF = {
5783
+ __proto__: null,
5784
+ [ValueProperties]: PURE
5785
+ };
5786
+ /* PURE FUNCTION IF FIRST ARG DOES NOT CONTAIN A GETTER */
5787
+ const PF_NO_GETTER = {
5788
+ __proto__: null,
5789
+ [ValueProperties]: GETTER_ACCESS
5790
+ };
5791
+ /* FUNCTION THAT MUTATES FIRST ARG WITHOUT TRIGGERING ACCESSORS */
5792
+ const MUTATES_ARG_WITHOUT_ACCESSOR = {
5793
+ __proto__: null,
5794
+ [ValueProperties]: {
5795
+ deoptimizeArgumentsOnCall({ args: [, firstArgument] }) {
5796
+ firstArgument?.deoptimizePath(UNKNOWN_PATH);
5797
+ },
5798
+ getLiteralValue: getTruthyLiteralValue,
5799
+ hasEffectsWhenCalled({ args }, context) {
5800
+ return (args.length <= 1 ||
5801
+ args[1].hasEffectsOnInteractionAtPath(UNKNOWN_NON_ACCESSOR_PATH, NODE_INTERACTION_UNKNOWN_ASSIGNMENT, context));
5812
5802
  }
5813
- return this.additionalInitializers;
5814
5803
  }
5815
- }
5816
-
5817
- const MAX_TRACKED_INTERACTIONS = 20;
5818
- const NO_INTERACTIONS = EMPTY_ARRAY;
5819
- const UNKNOWN_DEOPTIMIZED_FIELD = new Set([UnknownKey]);
5820
- const EMPTY_PATH_TRACKER = new PathTracker();
5821
- const UNKNOWN_DEOPTIMIZED_ENTITY = new Set([UNKNOWN_EXPRESSION]);
5822
- class ParameterVariable extends LocalVariable {
5823
- constructor(name, declarator, context) {
5824
- super(name, declarator, UNKNOWN_EXPRESSION, context, 'parameter');
5825
- this.deoptimizationInteractions = [];
5826
- this.deoptimizations = new PathTracker();
5827
- this.deoptimizedFields = new Set();
5828
- this.entitiesToBeDeoptimized = new Set();
5829
- this.knownExpressionsToBeDeoptimized = [];
5830
- this.knownValue = UNKNOWN_EXPRESSION;
5831
- }
5832
- addEntityToBeDeoptimized(entity) {
5833
- if (entity === UNKNOWN_EXPRESSION) {
5834
- // As unknown expressions fully deoptimize all interactions, we can clear
5835
- // the interaction cache at this point provided we keep this optimization
5836
- // in mind when adding new interactions
5837
- if (!this.entitiesToBeDeoptimized.has(UNKNOWN_EXPRESSION)) {
5838
- this.entitiesToBeDeoptimized.add(UNKNOWN_EXPRESSION);
5839
- for (const { interaction } of this.deoptimizationInteractions) {
5840
- deoptimizeInteraction(interaction);
5841
- }
5842
- this.deoptimizationInteractions = NO_INTERACTIONS;
5843
- }
5844
- }
5845
- else if (this.deoptimizedFields.has(UnknownKey)) {
5846
- // This means that we already deoptimized all interactions and no longer
5847
- // track them
5848
- entity.deoptimizePath(UNKNOWN_PATH);
5849
- }
5850
- else if (!this.entitiesToBeDeoptimized.has(entity)) {
5851
- this.entitiesToBeDeoptimized.add(entity);
5852
- for (const field of this.deoptimizedFields) {
5853
- entity.deoptimizePath([field]);
5854
- }
5855
- for (const { interaction, path } of this.deoptimizationInteractions) {
5856
- entity.deoptimizeArgumentsOnInteractionAtPath(interaction, path, SHARED_RECURSION_TRACKER);
5857
- }
5858
- }
5859
- }
5860
- markReassigned() {
5861
- if (this.isReassigned) {
5862
- return;
5863
- }
5864
- super.markReassigned();
5865
- for (const expression of this.knownExpressionsToBeDeoptimized) {
5866
- expression.deoptimizeCache();
5867
- }
5868
- this.knownExpressionsToBeDeoptimized = [];
5869
- }
5870
- /**
5871
- * If we are sure about the value of this parameter, we can set it here.
5872
- * It can be a literal or the only possible value of the parameter.
5873
- * an undefined value means that the parameter is not known.
5874
- * @param value The known value of the parameter to be set.
5875
- */
5876
- setKnownValue(value) {
5877
- if (this.isReassigned) {
5878
- return;
5879
- }
5880
- if (this.knownValue !== value) {
5881
- for (const expression of this.knownExpressionsToBeDeoptimized) {
5882
- expression.deoptimizeCache();
5883
- }
5884
- this.knownExpressionsToBeDeoptimized = [];
5885
- }
5886
- this.knownValue = value;
5887
- }
5888
- getLiteralValueAtPath(path, recursionTracker, origin) {
5889
- if (this.isReassigned) {
5890
- return UnknownValue;
5891
- }
5892
- this.knownExpressionsToBeDeoptimized.push(origin);
5893
- return recursionTracker.withTrackedEntityAtPath(path, this.knownValue, () => this.knownValue.getLiteralValueAtPath(path, recursionTracker, origin), UnknownValue);
5894
- }
5895
- hasEffectsOnInteractionAtPath(path, interaction, context) {
5896
- // assigned is a bit different, since the value has a new name (the parameter)
5897
- return interaction.type === INTERACTION_ASSIGNED
5898
- ? super.hasEffectsOnInteractionAtPath(path, interaction, context)
5899
- : this.knownValue.hasEffectsOnInteractionAtPath(path, interaction, context);
5900
- }
5901
- deoptimizeArgumentsOnInteractionAtPath(interaction, path) {
5902
- // For performance reasons, we fully deoptimize all deeper interactions
5903
- if (path.length >= 2 ||
5904
- this.entitiesToBeDeoptimized.has(UNKNOWN_EXPRESSION) ||
5905
- this.deoptimizationInteractions.length >= MAX_TRACKED_INTERACTIONS ||
5906
- (path.length === 1 &&
5907
- (this.deoptimizedFields.has(UnknownKey) ||
5908
- (interaction.type === INTERACTION_CALLED && this.deoptimizedFields.has(path[0]))))) {
5909
- deoptimizeInteraction(interaction);
5910
- return;
5911
- }
5912
- if (!this.deoptimizations.trackEntityAtPathAndGetIfTracked(path, interaction.args)) {
5913
- for (const entity of this.entitiesToBeDeoptimized) {
5914
- entity.deoptimizeArgumentsOnInteractionAtPath(interaction, path, SHARED_RECURSION_TRACKER);
5915
- }
5916
- if (!this.entitiesToBeDeoptimized.has(UNKNOWN_EXPRESSION)) {
5917
- this.deoptimizationInteractions.push({
5918
- interaction,
5919
- path
5920
- });
5921
- }
5922
- }
5923
- }
5924
- deoptimizePath(path) {
5925
- if (path.length === 0) {
5926
- this.markReassigned();
5927
- return;
5928
- }
5929
- if (this.deoptimizedFields.has(UnknownKey)) {
5930
- return;
5931
- }
5932
- const key = path[0];
5933
- if (this.deoptimizedFields.has(key)) {
5934
- return;
5935
- }
5936
- this.deoptimizedFields.add(key);
5937
- for (const entity of this.entitiesToBeDeoptimized) {
5938
- // We do not need a recursion tracker here as we already track whether
5939
- // this field is deoptimized
5940
- entity.deoptimizePath([key]);
5941
- }
5942
- if (key === UnknownKey) {
5943
- // save some memory
5944
- this.deoptimizationInteractions = NO_INTERACTIONS;
5945
- this.deoptimizations = EMPTY_PATH_TRACKER;
5946
- this.deoptimizedFields = UNKNOWN_DEOPTIMIZED_FIELD;
5947
- this.entitiesToBeDeoptimized = UNKNOWN_DEOPTIMIZED_ENTITY;
5948
- }
5949
- }
5950
- getReturnExpressionWhenCalledAtPath(path) {
5951
- // We deoptimize everything that is called as that will trivially deoptimize
5952
- // the corresponding return expressions as well and avoid badly performing
5953
- // and complicated alternatives
5954
- if (path.length === 0) {
5955
- this.deoptimizePath(UNKNOWN_PATH);
5956
- }
5957
- else if (!this.deoptimizedFields.has(path[0])) {
5958
- this.deoptimizePath([path[0]]);
5959
- }
5960
- return UNKNOWN_RETURN_EXPRESSION;
5961
- }
5962
- }
5963
-
5964
- const chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_$';
5965
- const base = 64;
5966
- function toBase64(value) {
5967
- let outString = '';
5968
- do {
5969
- const currentDigit = value % base;
5970
- value = (value / base) | 0;
5971
- outString = chars[currentDigit] + outString;
5972
- } while (value !== 0);
5973
- return outString;
5974
- }
5975
-
5976
- function getSafeName(baseName, usedNames, forbiddenNames) {
5977
- let safeName = baseName;
5978
- let count = 1;
5979
- while (usedNames.has(safeName) || RESERVED_NAMES.has(safeName) || forbiddenNames?.has(safeName)) {
5980
- safeName = `${baseName}$${toBase64(count++)}`;
5981
- }
5982
- usedNames.add(safeName);
5983
- return safeName;
5984
- }
5985
-
5986
- class Scope {
5987
- constructor() {
5988
- this.children = [];
5989
- this.variables = new Map();
5990
- }
5991
- /*
5992
- Redeclaration rules:
5993
- - var can redeclare var
5994
- - in function scopes, function and var can redeclare function and var
5995
- - var is hoisted across scopes, function remains in the scope it is declared
5996
- - var and function can redeclare function parameters, but parameters cannot redeclare parameters
5997
- - function cannot redeclare catch scope parameters
5998
- - var can redeclare catch scope parameters in a way
5999
- - if the parameter is an identifier and not a pattern
6000
- - then the variable is still declared in the hoisted outer scope, but the initializer is assigned to the parameter
6001
- - const, let, class, and function except in the cases above cannot redeclare anything
6002
- */
6003
- addDeclaration(identifier, context, init, kind) {
6004
- const name = identifier.name;
6005
- const existingVariable = this.hoistedVariables?.get(name) || this.variables.get(name);
6006
- if (existingVariable) {
6007
- const existingKind = existingVariable.kind;
6008
- if (kind === 'var' && existingKind === 'var') {
6009
- existingVariable.addDeclaration(identifier, init);
6010
- return existingVariable;
6011
- }
6012
- context.error(logRedeclarationError(name), identifier.start);
6013
- }
6014
- const newVariable = new LocalVariable(identifier.name, identifier, init, context, kind);
6015
- this.variables.set(name, newVariable);
6016
- return newVariable;
6017
- }
6018
- addHoistedVariable(name, variable) {
6019
- (this.hoistedVariables ||= new Map()).set(name, variable);
6020
- }
6021
- contains(name) {
6022
- return this.variables.has(name);
6023
- }
6024
- findVariable(_name) {
6025
- /* istanbul ignore next */
6026
- throw new Error('Internal Error: findVariable needs to be implemented by a subclass');
6027
- }
6028
- }
6029
-
6030
- class ChildScope extends Scope {
6031
- constructor(parent, context) {
6032
- super();
6033
- this.parent = parent;
6034
- this.context = context;
6035
- this.accessedOutsideVariables = new Map();
6036
- parent.children.push(this);
6037
- }
6038
- addAccessedDynamicImport(importExpression) {
6039
- (this.accessedDynamicImports || (this.accessedDynamicImports = new Set())).add(importExpression);
6040
- if (this.parent instanceof ChildScope) {
6041
- this.parent.addAccessedDynamicImport(importExpression);
6042
- }
6043
- }
6044
- addAccessedGlobals(globals, accessedGlobalsByScope) {
6045
- const accessedGlobals = accessedGlobalsByScope.get(this) || new Set();
6046
- for (const name of globals) {
6047
- accessedGlobals.add(name);
6048
- }
6049
- accessedGlobalsByScope.set(this, accessedGlobals);
6050
- if (this.parent instanceof ChildScope) {
6051
- this.parent.addAccessedGlobals(globals, accessedGlobalsByScope);
6052
- }
6053
- }
6054
- addNamespaceMemberAccess(name, variable) {
6055
- this.accessedOutsideVariables.set(name, variable);
6056
- this.parent.addNamespaceMemberAccess(name, variable);
6057
- }
6058
- addReturnExpression(expression) {
6059
- this.parent instanceof ChildScope && this.parent.addReturnExpression(expression);
6060
- }
6061
- addUsedOutsideNames(usedNames, format, exportNamesByVariable, accessedGlobalsByScope) {
6062
- for (const variable of this.accessedOutsideVariables.values()) {
6063
- if (variable.included) {
6064
- usedNames.add(variable.getBaseVariableName());
6065
- if (format === 'system' && exportNamesByVariable.has(variable)) {
6066
- usedNames.add('exports');
6067
- }
6068
- }
6069
- }
6070
- const accessedGlobals = accessedGlobalsByScope.get(this);
6071
- if (accessedGlobals) {
6072
- for (const name of accessedGlobals) {
6073
- usedNames.add(name);
6074
- }
6075
- }
6076
- }
6077
- contains(name) {
6078
- return this.variables.has(name) || this.parent.contains(name);
6079
- }
6080
- deconflict(format, exportNamesByVariable, accessedGlobalsByScope) {
6081
- const usedNames = new Set();
6082
- this.addUsedOutsideNames(usedNames, format, exportNamesByVariable, accessedGlobalsByScope);
6083
- if (this.accessedDynamicImports) {
6084
- for (const importExpression of this.accessedDynamicImports) {
6085
- if (importExpression.inlineNamespace) {
6086
- usedNames.add(importExpression.inlineNamespace.getBaseVariableName());
6087
- }
6088
- }
6089
- }
6090
- for (const [name, variable] of this.variables) {
6091
- if (variable.included || variable.alwaysRendered) {
6092
- variable.setRenderNames(null, getSafeName(name, usedNames, variable.forbiddenNames));
6093
- }
6094
- }
6095
- for (const scope of this.children) {
6096
- scope.deconflict(format, exportNamesByVariable, accessedGlobalsByScope);
6097
- }
6098
- }
6099
- findLexicalBoundary() {
6100
- return this.parent.findLexicalBoundary();
6101
- }
6102
- findVariable(name) {
6103
- const knownVariable = this.variables.get(name) || this.accessedOutsideVariables.get(name);
6104
- if (knownVariable) {
6105
- return knownVariable;
6106
- }
6107
- const variable = this.parent.findVariable(name);
6108
- this.accessedOutsideVariables.set(name, variable);
6109
- return variable;
6110
- }
6111
- }
6112
-
6113
- class CatchBodyScope extends ChildScope {
6114
- constructor(parent) {
6115
- super(parent, parent.context);
6116
- this.parent = parent;
6117
- }
6118
- addDeclaration(identifier, context, init, kind) {
6119
- if (kind === 'var') {
6120
- const name = identifier.name;
6121
- const existingVariable = this.hoistedVariables?.get(name) || this.variables.get(name);
6122
- if (existingVariable) {
6123
- const existingKind = existingVariable.kind;
6124
- if (existingKind === 'parameter' &&
6125
- // If this is a destructured parameter, it is forbidden to redeclare
6126
- existingVariable.declarations[0].parent.type === CatchClause$1) {
6127
- // If this is a var with the same name as the catch scope parameter,
6128
- // the assignment actually goes to the parameter and the var is
6129
- // hoisted without assignment. Locally, it is shadowed by the
6130
- // parameter
6131
- const declaredVariable = this.parent.parent.addDeclaration(identifier, context, UNDEFINED_EXPRESSION, kind);
6132
- // To avoid the need to rewrite the declaration, we link the variable
6133
- // names. If we ever implement a logic that splits initialization and
6134
- // assignment for hoisted vars, the "renderLikeHoisted" logic can be
6135
- // removed again.
6136
- // We do not need to check whether there already is a linked
6137
- // variable because then declaredVariable would be that linked
6138
- // variable.
6139
- existingVariable.renderLikeHoisted(declaredVariable);
6140
- this.addHoistedVariable(name, declaredVariable);
6141
- return declaredVariable;
6142
- }
6143
- if (existingKind === 'var') {
6144
- existingVariable.addDeclaration(identifier, init);
6145
- return existingVariable;
6146
- }
6147
- return context.error(logRedeclarationError(name), identifier.start);
6148
- }
6149
- // We only add parameters to parameter scopes
6150
- const declaredVariable = this.parent.parent.addDeclaration(identifier, context, init, kind);
6151
- // Necessary to make sure the init is deoptimized for conditional declarations.
6152
- // We cannot call deoptimizePath here.
6153
- declaredVariable.markInitializersForDeoptimization();
6154
- // We add the variable to this and all parent scopes to reliably detect conflicts
6155
- this.addHoistedVariable(name, declaredVariable);
6156
- return declaredVariable;
6157
- }
6158
- return super.addDeclaration(identifier, context, init, kind);
6159
- }
6160
- }
6161
-
6162
- class FunctionBodyScope extends ChildScope {
6163
- constructor(parent) {
6164
- super(parent, parent.context);
6165
- }
6166
- // There is stuff that is only allowed in function scopes, i.e. functions can
6167
- // be redeclared, functions and var can redeclare each other
6168
- addDeclaration(identifier, context, init, kind) {
6169
- const name = identifier.name;
6170
- const existingVariable = this.hoistedVariables?.get(name) || this.variables.get(name);
6171
- if (existingVariable) {
6172
- const existingKind = existingVariable.kind;
6173
- if ((kind === 'var' || kind === 'function') &&
6174
- (existingKind === 'var' || existingKind === 'function' || existingKind === 'parameter')) {
6175
- existingVariable.addDeclaration(identifier, init);
6176
- return existingVariable;
6177
- }
6178
- context.error(logRedeclarationError(name), identifier.start);
6179
- }
6180
- const newVariable = new LocalVariable(identifier.name, identifier, init, context, kind);
6181
- this.variables.set(name, newVariable);
6182
- return newVariable;
6183
- }
6184
- }
6185
-
6186
- class ParameterScope extends ChildScope {
6187
- constructor(parent, isCatchScope) {
6188
- super(parent, parent.context);
6189
- this.parameters = [];
6190
- this.hasRest = false;
6191
- this.bodyScope = isCatchScope ? new CatchBodyScope(this) : new FunctionBodyScope(this);
6192
- }
6193
- /**
6194
- * Adds a parameter to this scope. Parameters must be added in the correct
6195
- * order, i.e. from left to right.
6196
- */
6197
- addParameterDeclaration(identifier) {
6198
- const { name, start } = identifier;
6199
- const existingParameter = this.variables.get(name);
6200
- if (existingParameter) {
6201
- return this.context.error(logDuplicateArgumentNameError(name), start);
6202
- }
6203
- const variable = new ParameterVariable(name, identifier, this.context);
6204
- this.variables.set(name, variable);
6205
- // We also add it to the body scope to detect name conflicts with local
6206
- // variables. We still need the intermediate scope, though, as parameter
6207
- // defaults are NOT taken from the body scope but from the parameters or
6208
- // outside scope.
6209
- this.bodyScope.addHoistedVariable(name, variable);
6210
- return variable;
6211
- }
6212
- addParameterVariables(parameters, hasRest) {
6213
- this.parameters = parameters;
6214
- for (const parameterList of parameters) {
6215
- for (const parameter of parameterList) {
6216
- parameter.alwaysRendered = true;
6217
- }
6218
- }
6219
- this.hasRest = hasRest;
6220
- }
6221
- includeCallArguments(context, parameters) {
6222
- let calledFromTryStatement = false;
6223
- let argumentIncluded = false;
6224
- const restParameter = this.hasRest && this.parameters[this.parameters.length - 1];
6225
- for (const checkedArgument of parameters) {
6226
- if (checkedArgument instanceof SpreadElement) {
6227
- for (const argument of parameters) {
6228
- argument.include(context, false);
6229
- }
6230
- break;
6231
- }
6232
- }
6233
- for (let index = parameters.length - 1; index >= 0; index--) {
6234
- const parameterVariables = this.parameters[index] || restParameter;
6235
- const argument = parameters[index];
6236
- if (parameterVariables) {
6237
- calledFromTryStatement = false;
6238
- if (parameterVariables.length === 0) {
6239
- // handle empty destructuring
6240
- argumentIncluded = true;
6241
- }
6242
- else {
6243
- for (const variable of parameterVariables) {
6244
- if (variable.included) {
6245
- argumentIncluded = true;
6246
- }
6247
- if (variable.calledFromTryStatement) {
6248
- calledFromTryStatement = true;
6249
- }
6250
- }
6251
- }
6252
- }
6253
- if (!argumentIncluded && argument.shouldBeIncluded(context)) {
6254
- argumentIncluded = true;
6255
- }
6256
- if (argumentIncluded) {
6257
- argument.include(context, calledFromTryStatement);
6258
- }
6259
- }
6260
- }
6261
- }
6262
-
6263
- class ReturnValueScope extends ParameterScope {
6264
- constructor() {
6265
- super(...arguments);
6266
- this.returnExpression = null;
6267
- this.returnExpressions = [];
6268
- }
6269
- addReturnExpression(expression) {
6270
- this.returnExpressions.push(expression);
6271
- }
6272
- getReturnExpression() {
6273
- if (this.returnExpression === null)
6274
- this.updateReturnExpression();
6275
- return this.returnExpression;
6276
- }
6277
- updateReturnExpression() {
6278
- if (this.returnExpressions.length === 1) {
6279
- this.returnExpression = this.returnExpressions[0];
6280
- }
6281
- else {
6282
- this.returnExpression = UNKNOWN_EXPRESSION;
6283
- for (const expression of this.returnExpressions) {
6284
- expression.deoptimizePath(UNKNOWN_PATH);
6285
- }
6286
- }
6287
- }
6288
- }
6289
-
6290
- /** @typedef { import('estree').Node} Node */
6291
- /** @typedef {Node | {
6292
- * type: 'PropertyDefinition';
6293
- * computed: boolean;
6294
- * value: Node
6295
- * }} NodeWithPropertyDefinition */
6296
-
6297
- /**
6298
- *
6299
- * @param {NodeWithPropertyDefinition} node
6300
- * @param {NodeWithPropertyDefinition} parent
6301
- * @returns {boolean}
6302
- */
6303
- function is_reference (node, parent) {
6304
- if (node.type === 'MemberExpression') {
6305
- return !node.computed && is_reference(node.object, node);
6306
- }
6307
-
6308
- if (node.type === 'Identifier') {
6309
- if (!parent) return true;
6310
-
6311
- switch (parent.type) {
6312
- // disregard `bar` in `foo.bar`
6313
- case 'MemberExpression': return parent.computed || node === parent.object;
6314
-
6315
- // disregard the `foo` in `class {foo(){}}` but keep it in `class {[foo](){}}`
6316
- case 'MethodDefinition': return parent.computed;
6317
-
6318
- // disregard the `foo` in `class {foo=bar}` but keep it in `class {[foo]=bar}` and `class {bar=foo}`
6319
- case 'PropertyDefinition': return parent.computed || node === parent.value;
6320
-
6321
- // disregard the `bar` in `{ bar: foo }`, but keep it in `{ [bar]: foo }`
6322
- case 'Property': return parent.computed || node === parent.value;
6323
-
6324
- // disregard the `bar` in `export { foo as bar }` or
6325
- // the foo in `import { foo as bar }`
6326
- case 'ExportSpecifier':
6327
- case 'ImportSpecifier': return node === parent.local;
6328
-
6329
- // disregard the `foo` in `foo: while (...) { ... break foo; ... continue foo;}`
6330
- case 'LabeledStatement':
6331
- case 'BreakStatement':
6332
- case 'ContinueStatement': return false;
6333
- default: return true;
6334
- }
6335
- }
6336
-
6337
- return false;
6338
- }
6339
-
6340
- const PureFunctionKey = Symbol('PureFunction');
6341
- const getPureFunctions = ({ treeshake }) => {
6342
- const pureFunctions = Object.create(null);
6343
- for (const functionName of treeshake ? treeshake.manualPureFunctions : []) {
6344
- let currentFunctions = pureFunctions;
6345
- for (const pathSegment of functionName.split('.')) {
6346
- currentFunctions = currentFunctions[pathSegment] ||= Object.create(null);
6347
- }
6348
- currentFunctions[PureFunctionKey] = true;
6349
- }
6350
- return pureFunctions;
6351
- };
6352
-
6353
- const doNothing = () => { };
6354
-
6355
- /* eslint sort-keys: "off" */
6356
- const ValueProperties = Symbol('Value Properties');
6357
- const getTruthyLiteralValue = () => UnknownTruthyValue;
6358
- const returnFalse = () => false;
6359
- const returnTrue = () => true;
6360
- const PURE = {
6361
- deoptimizeArgumentsOnCall: doNothing,
6362
- getLiteralValue: getTruthyLiteralValue,
6363
- hasEffectsWhenCalled: returnFalse
6364
- };
6365
- const IMPURE = {
6366
- deoptimizeArgumentsOnCall: doNothing,
6367
- getLiteralValue: getTruthyLiteralValue,
6368
- hasEffectsWhenCalled: returnTrue
6369
- };
6370
- const PURE_WITH_ARRAY = {
6371
- deoptimizeArgumentsOnCall: doNothing,
6372
- getLiteralValue: getTruthyLiteralValue,
6373
- hasEffectsWhenCalled({ args }) {
6374
- return args.length > 1 && !(args[1] instanceof ArrayExpression);
6375
- }
6376
- };
6377
- const GETTER_ACCESS = {
6378
- deoptimizeArgumentsOnCall: doNothing,
6379
- getLiteralValue: getTruthyLiteralValue,
6380
- hasEffectsWhenCalled({ args }, context) {
6381
- const [_thisArgument, firstArgument] = args;
6382
- return (!(firstArgument instanceof ExpressionEntity) ||
6383
- firstArgument.hasEffectsOnInteractionAtPath(UNKNOWN_PATH, NODE_INTERACTION_UNKNOWN_ACCESS, context));
6384
- }
6385
- };
6386
- // We use shortened variables to reduce file size here
6387
- /* OBJECT */
6388
- const O = {
6389
- __proto__: null,
6390
- [ValueProperties]: IMPURE
6391
- };
6392
- /* PURE FUNCTION */
6393
- const PF = {
6394
- __proto__: null,
6395
- [ValueProperties]: PURE
6396
- };
6397
- /* PURE FUNCTION IF FIRST ARG DOES NOT CONTAIN A GETTER */
6398
- const PF_NO_GETTER = {
6399
- __proto__: null,
6400
- [ValueProperties]: GETTER_ACCESS
6401
- };
6402
- /* FUNCTION THAT MUTATES FIRST ARG WITHOUT TRIGGERING ACCESSORS */
6403
- const MUTATES_ARG_WITHOUT_ACCESSOR = {
6404
- __proto__: null,
6405
- [ValueProperties]: {
6406
- deoptimizeArgumentsOnCall({ args: [, firstArgument] }) {
6407
- firstArgument?.deoptimizePath(UNKNOWN_PATH);
6408
- },
6409
- getLiteralValue: getTruthyLiteralValue,
6410
- hasEffectsWhenCalled({ args }, context) {
6411
- return (args.length <= 1 ||
6412
- args[1].hasEffectsOnInteractionAtPath(UNKNOWN_NON_ACCESSOR_PATH, NODE_INTERACTION_UNKNOWN_ASSIGNMENT, context));
6413
- }
6414
- }
6415
- };
6416
- /* CONSTRUCTOR */
6417
- const C = {
6418
- __proto__: null,
6419
- [ValueProperties]: IMPURE,
6420
- prototype: O
6421
- };
6422
- /* PURE CONSTRUCTOR */
6423
- const PC = {
6424
- __proto__: null,
6425
- [ValueProperties]: PURE,
6426
- prototype: O
6427
- };
6428
- const PC_WITH_ARRAY = {
6429
- __proto__: null,
6430
- [ValueProperties]: PURE_WITH_ARRAY,
6431
- prototype: O
6432
- };
6433
- const ARRAY_TYPE = {
6434
- __proto__: null,
6435
- [ValueProperties]: PURE,
6436
- from: O,
6437
- of: PF,
6438
- prototype: O
6439
- };
6440
- const INTL_MEMBER = {
6441
- __proto__: null,
6442
- [ValueProperties]: PURE,
6443
- supportedLocalesOf: PC
6444
- };
6445
- const knownGlobals = {
6446
- // Placeholders for global objects to avoid shape mutations
6447
- global: O,
6448
- globalThis: O,
6449
- self: O,
6450
- window: O,
6451
- // Common globals
6452
- __proto__: null,
6453
- [ValueProperties]: IMPURE,
6454
- Array: {
6455
- __proto__: null,
6456
- [ValueProperties]: IMPURE,
6457
- from: O,
6458
- isArray: PF,
6459
- of: PF,
6460
- prototype: O
6461
- },
6462
- ArrayBuffer: {
6463
- __proto__: null,
6464
- [ValueProperties]: PURE,
6465
- isView: PF,
6466
- prototype: O
6467
- },
6468
- Atomics: O,
6469
- BigInt: C,
6470
- BigInt64Array: C,
6471
- BigUint64Array: C,
6472
- Boolean: PC,
6473
- constructor: C,
6474
- DataView: PC,
6475
- Date: {
6476
- __proto__: null,
6477
- [ValueProperties]: PURE,
6478
- now: PF,
6479
- parse: PF,
6480
- prototype: O,
6481
- UTC: PF
6482
- },
6483
- decodeURI: PF,
6484
- decodeURIComponent: PF,
6485
- encodeURI: PF,
6486
- encodeURIComponent: PF,
6487
- Error: PC,
6488
- escape: PF,
6489
- eval: O,
6490
- EvalError: PC,
6491
- Float32Array: ARRAY_TYPE,
6492
- Float64Array: ARRAY_TYPE,
6493
- Function: C,
6494
- hasOwnProperty: O,
6495
- Infinity: O,
6496
- Int16Array: ARRAY_TYPE,
6497
- Int32Array: ARRAY_TYPE,
6498
- Int8Array: ARRAY_TYPE,
6499
- isFinite: PF,
6500
- isNaN: PF,
6501
- isPrototypeOf: O,
6502
- JSON: O,
6503
- Map: PC_WITH_ARRAY,
6504
- Math: {
6505
- __proto__: null,
6506
- [ValueProperties]: IMPURE,
6507
- abs: PF,
6508
- acos: PF,
6509
- acosh: PF,
6510
- asin: PF,
6511
- asinh: PF,
6512
- atan: PF,
6513
- atan2: PF,
6514
- atanh: PF,
6515
- cbrt: PF,
6516
- ceil: PF,
6517
- clz32: PF,
6518
- cos: PF,
6519
- cosh: PF,
6520
- exp: PF,
6521
- expm1: PF,
6522
- floor: PF,
6523
- fround: PF,
6524
- hypot: PF,
6525
- imul: PF,
6526
- log: PF,
6527
- log10: PF,
6528
- log1p: PF,
6529
- log2: PF,
6530
- max: PF,
6531
- min: PF,
6532
- pow: PF,
6533
- random: PF,
6534
- round: PF,
6535
- sign: PF,
6536
- sin: PF,
6537
- sinh: PF,
6538
- sqrt: PF,
6539
- tan: PF,
6540
- tanh: PF,
6541
- trunc: PF
6542
- },
6543
- NaN: O,
6544
- Number: {
6545
- __proto__: null,
6546
- [ValueProperties]: PURE,
6547
- isFinite: PF,
6548
- isInteger: PF,
6549
- isNaN: PF,
6550
- isSafeInteger: PF,
6551
- parseFloat: PF,
6552
- parseInt: PF,
6553
- prototype: O
6554
- },
6555
- Object: {
6556
- __proto__: null,
6557
- [ValueProperties]: PURE,
6558
- create: PF,
6559
- // Technically those can throw in certain situations, but we ignore this as
6560
- // code that relies on this will hopefully wrap this in a try-catch, which
6561
- // deoptimizes everything anyway
6562
- defineProperty: MUTATES_ARG_WITHOUT_ACCESSOR,
6563
- defineProperties: MUTATES_ARG_WITHOUT_ACCESSOR,
6564
- freeze: MUTATES_ARG_WITHOUT_ACCESSOR,
6565
- getOwnPropertyDescriptor: PF,
6566
- getOwnPropertyDescriptors: PF,
6567
- getOwnPropertyNames: PF,
6568
- getOwnPropertySymbols: PF,
6569
- getPrototypeOf: PF,
6570
- hasOwn: PF,
6571
- is: PF,
6572
- isExtensible: PF,
6573
- isFrozen: PF,
6574
- isSealed: PF,
6575
- keys: PF,
6576
- fromEntries: O,
6577
- entries: PF_NO_GETTER,
6578
- values: PF_NO_GETTER,
6579
- prototype: O
6580
- },
6581
- parseFloat: PF,
6582
- parseInt: PF,
6583
- Promise: {
6584
- __proto__: null,
6585
- [ValueProperties]: IMPURE,
6586
- all: O,
6587
- allSettled: O,
6588
- any: O,
6589
- prototype: O,
6590
- race: O,
6591
- reject: O,
6592
- resolve: O
6593
- },
6594
- propertyIsEnumerable: O,
6595
- Proxy: O,
6596
- RangeError: PC,
6597
- ReferenceError: PC,
6598
- Reflect: O,
6599
- RegExp: PC,
6600
- Set: PC_WITH_ARRAY,
6601
- SharedArrayBuffer: C,
6602
- String: {
6603
- __proto__: null,
6604
- [ValueProperties]: PURE,
6605
- fromCharCode: PF,
6606
- fromCodePoint: PF,
6607
- prototype: O,
6608
- raw: PF
6609
- },
6610
- Symbol: {
6611
- __proto__: null,
6612
- [ValueProperties]: PURE,
6613
- for: PF,
6614
- keyFor: PF,
6615
- prototype: O,
6616
- toStringTag: {
6617
- __proto__: null,
6618
- [ValueProperties]: {
6619
- deoptimizeArgumentsOnCall: doNothing,
6620
- getLiteralValue() {
6621
- return SymbolToStringTag;
6622
- },
6623
- hasEffectsWhenCalled: returnTrue
5804
+ };
5805
+ /* CONSTRUCTOR */
5806
+ const C = {
5807
+ __proto__: null,
5808
+ [ValueProperties]: IMPURE,
5809
+ prototype: O
5810
+ };
5811
+ /* PURE CONSTRUCTOR */
5812
+ const PC = {
5813
+ __proto__: null,
5814
+ [ValueProperties]: PURE,
5815
+ prototype: O
5816
+ };
5817
+ const PC_WITH_ARRAY = {
5818
+ __proto__: null,
5819
+ [ValueProperties]: PURE_WITH_ARRAY,
5820
+ prototype: O
5821
+ };
5822
+ const ARRAY_TYPE = {
5823
+ __proto__: null,
5824
+ [ValueProperties]: PURE,
5825
+ from: O,
5826
+ of: PF,
5827
+ prototype: O
5828
+ };
5829
+ const INTL_MEMBER = {
5830
+ __proto__: null,
5831
+ [ValueProperties]: PURE,
5832
+ supportedLocalesOf: PC
5833
+ };
5834
+ const knownGlobals = {
5835
+ // Placeholders for global objects to avoid shape mutations
5836
+ global: O,
5837
+ globalThis: O,
5838
+ self: O,
5839
+ window: O,
5840
+ // Common globals
5841
+ __proto__: null,
5842
+ [ValueProperties]: IMPURE,
5843
+ Array: {
5844
+ __proto__: null,
5845
+ [ValueProperties]: IMPURE,
5846
+ from: O,
5847
+ isArray: PF,
5848
+ of: PF,
5849
+ prototype: O
5850
+ },
5851
+ ArrayBuffer: {
5852
+ __proto__: null,
5853
+ [ValueProperties]: PURE,
5854
+ isView: PF,
5855
+ prototype: O
5856
+ },
5857
+ Atomics: O,
5858
+ BigInt: C,
5859
+ BigInt64Array: C,
5860
+ BigUint64Array: C,
5861
+ Boolean: PC,
5862
+ constructor: C,
5863
+ DataView: PC,
5864
+ Date: {
5865
+ __proto__: null,
5866
+ [ValueProperties]: PURE,
5867
+ now: PF,
5868
+ parse: PF,
5869
+ prototype: O,
5870
+ UTC: PF
5871
+ },
5872
+ decodeURI: PF,
5873
+ decodeURIComponent: PF,
5874
+ encodeURI: PF,
5875
+ encodeURIComponent: PF,
5876
+ Error: PC,
5877
+ escape: PF,
5878
+ eval: O,
5879
+ EvalError: PC,
5880
+ Float32Array: ARRAY_TYPE,
5881
+ Float64Array: ARRAY_TYPE,
5882
+ Function: C,
5883
+ hasOwnProperty: O,
5884
+ Infinity: O,
5885
+ Int16Array: ARRAY_TYPE,
5886
+ Int32Array: ARRAY_TYPE,
5887
+ Int8Array: ARRAY_TYPE,
5888
+ isFinite: PF,
5889
+ isNaN: PF,
5890
+ isPrototypeOf: O,
5891
+ JSON: O,
5892
+ Map: PC_WITH_ARRAY,
5893
+ Math: {
5894
+ __proto__: null,
5895
+ [ValueProperties]: IMPURE,
5896
+ abs: PF,
5897
+ acos: PF,
5898
+ acosh: PF,
5899
+ asin: PF,
5900
+ asinh: PF,
5901
+ atan: PF,
5902
+ atan2: PF,
5903
+ atanh: PF,
5904
+ cbrt: PF,
5905
+ ceil: PF,
5906
+ clz32: PF,
5907
+ cos: PF,
5908
+ cosh: PF,
5909
+ exp: PF,
5910
+ expm1: PF,
5911
+ floor: PF,
5912
+ fround: PF,
5913
+ hypot: PF,
5914
+ imul: PF,
5915
+ log: PF,
5916
+ log10: PF,
5917
+ log1p: PF,
5918
+ log2: PF,
5919
+ max: PF,
5920
+ min: PF,
5921
+ pow: PF,
5922
+ random: PF,
5923
+ round: PF,
5924
+ sign: PF,
5925
+ sin: PF,
5926
+ sinh: PF,
5927
+ sqrt: PF,
5928
+ tan: PF,
5929
+ tanh: PF,
5930
+ trunc: PF
5931
+ },
5932
+ NaN: O,
5933
+ Number: {
5934
+ __proto__: null,
5935
+ [ValueProperties]: PURE,
5936
+ isFinite: PF,
5937
+ isInteger: PF,
5938
+ isNaN: PF,
5939
+ isSafeInteger: PF,
5940
+ parseFloat: PF,
5941
+ parseInt: PF,
5942
+ prototype: O
5943
+ },
5944
+ Object: {
5945
+ __proto__: null,
5946
+ [ValueProperties]: PURE,
5947
+ create: PF,
5948
+ // Technically those can throw in certain situations, but we ignore this as
5949
+ // code that relies on this will hopefully wrap this in a try-catch, which
5950
+ // deoptimizes everything anyway
5951
+ defineProperty: MUTATES_ARG_WITHOUT_ACCESSOR,
5952
+ defineProperties: MUTATES_ARG_WITHOUT_ACCESSOR,
5953
+ freeze: MUTATES_ARG_WITHOUT_ACCESSOR,
5954
+ getOwnPropertyDescriptor: PF,
5955
+ getOwnPropertyDescriptors: PF,
5956
+ getOwnPropertyNames: PF,
5957
+ getOwnPropertySymbols: PF,
5958
+ getPrototypeOf: PF,
5959
+ hasOwn: PF,
5960
+ is: PF,
5961
+ isExtensible: PF,
5962
+ isFrozen: PF,
5963
+ isSealed: PF,
5964
+ keys: PF,
5965
+ fromEntries: O,
5966
+ entries: PF_NO_GETTER,
5967
+ values: PF_NO_GETTER,
5968
+ prototype: O
5969
+ },
5970
+ parseFloat: PF,
5971
+ parseInt: PF,
5972
+ Promise: {
5973
+ __proto__: null,
5974
+ [ValueProperties]: IMPURE,
5975
+ all: O,
5976
+ allSettled: O,
5977
+ any: O,
5978
+ prototype: O,
5979
+ race: O,
5980
+ reject: O,
5981
+ resolve: O
5982
+ },
5983
+ propertyIsEnumerable: O,
5984
+ Proxy: O,
5985
+ RangeError: PC,
5986
+ ReferenceError: PC,
5987
+ Reflect: O,
5988
+ RegExp: PC,
5989
+ Set: PC_WITH_ARRAY,
5990
+ SharedArrayBuffer: C,
5991
+ String: {
5992
+ __proto__: null,
5993
+ [ValueProperties]: PURE,
5994
+ fromCharCode: PF,
5995
+ fromCodePoint: PF,
5996
+ prototype: O,
5997
+ raw: PF
5998
+ },
5999
+ Symbol: {
6000
+ __proto__: null,
6001
+ [ValueProperties]: PURE,
6002
+ for: PF,
6003
+ keyFor: PF,
6004
+ prototype: O,
6005
+ toStringTag: {
6006
+ __proto__: null,
6007
+ [ValueProperties]: {
6008
+ deoptimizeArgumentsOnCall: doNothing,
6009
+ getLiteralValue() {
6010
+ return SymbolToStringTag;
6011
+ },
6012
+ hasEffectsWhenCalled: returnTrue
6624
6013
  }
6625
6014
  }
6626
6015
  },
@@ -7287,295 +6676,940 @@ const knownGlobals = {
7287
6676
  for (const global of ['window', 'global', 'self', 'globalThis']) {
7288
6677
  knownGlobals[global] = knownGlobals;
7289
6678
  }
7290
- function getGlobalAtPath(path) {
7291
- let currentGlobal = knownGlobals;
7292
- for (const pathSegment of path) {
7293
- if (typeof pathSegment !== 'string') {
7294
- return null;
6679
+ function getGlobalAtPath(path) {
6680
+ let currentGlobal = knownGlobals;
6681
+ for (const pathSegment of path) {
6682
+ if (typeof pathSegment !== 'string') {
6683
+ return null;
6684
+ }
6685
+ currentGlobal = currentGlobal[pathSegment];
6686
+ if (!currentGlobal) {
6687
+ return null;
6688
+ }
6689
+ }
6690
+ return currentGlobal[ValueProperties];
6691
+ }
6692
+
6693
+ class GlobalVariable extends Variable {
6694
+ constructor(name) {
6695
+ super(name);
6696
+ // Ensure we use live-bindings for globals as we do not know if they have
6697
+ // been reassigned
6698
+ this.markReassigned();
6699
+ }
6700
+ deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
6701
+ switch (interaction.type) {
6702
+ // While there is no point in testing these cases as at the moment, they
6703
+ // are also covered via other means, we keep them for completeness
6704
+ case INTERACTION_ACCESSED:
6705
+ case INTERACTION_ASSIGNED: {
6706
+ if (!getGlobalAtPath([this.name, ...path].slice(0, -1))) {
6707
+ super.deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker);
6708
+ }
6709
+ return;
6710
+ }
6711
+ case INTERACTION_CALLED: {
6712
+ const globalAtPath = getGlobalAtPath([this.name, ...path]);
6713
+ if (globalAtPath) {
6714
+ globalAtPath.deoptimizeArgumentsOnCall(interaction);
6715
+ }
6716
+ else {
6717
+ super.deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker);
6718
+ }
6719
+ return;
6720
+ }
6721
+ }
6722
+ }
6723
+ getLiteralValueAtPath(path, _recursionTracker, _origin) {
6724
+ const globalAtPath = getGlobalAtPath([this.name, ...path]);
6725
+ return globalAtPath ? globalAtPath.getLiteralValue() : UnknownValue;
6726
+ }
6727
+ hasEffectsOnInteractionAtPath(path, interaction, context) {
6728
+ switch (interaction.type) {
6729
+ case INTERACTION_ACCESSED: {
6730
+ if (path.length === 0) {
6731
+ // Technically, "undefined" is a global variable of sorts
6732
+ return this.name !== 'undefined' && !getGlobalAtPath([this.name]);
6733
+ }
6734
+ return !getGlobalAtPath([this.name, ...path].slice(0, -1));
6735
+ }
6736
+ case INTERACTION_ASSIGNED: {
6737
+ return true;
6738
+ }
6739
+ case INTERACTION_CALLED: {
6740
+ const globalAtPath = getGlobalAtPath([this.name, ...path]);
6741
+ return !globalAtPath || globalAtPath.hasEffectsWhenCalled(interaction, context);
6742
+ }
6743
+ }
6744
+ }
6745
+ }
6746
+
6747
+ class LocalVariable extends Variable {
6748
+ constructor(name, declarator, init, context, kind) {
6749
+ super(name);
6750
+ this.init = init;
6751
+ this.calledFromTryStatement = false;
6752
+ this.additionalInitializers = null;
6753
+ this.expressionsToBeDeoptimized = [];
6754
+ this.declarations = declarator ? [declarator] : [];
6755
+ this.deoptimizationTracker = context.deoptimizationTracker;
6756
+ this.module = context.module;
6757
+ this.kind = kind;
6758
+ }
6759
+ addDeclaration(identifier, init) {
6760
+ this.declarations.push(identifier);
6761
+ this.markInitializersForDeoptimization().push(init);
6762
+ }
6763
+ consolidateInitializers() {
6764
+ if (this.additionalInitializers) {
6765
+ for (const initializer of this.additionalInitializers) {
6766
+ initializer.deoptimizePath(UNKNOWN_PATH);
6767
+ }
6768
+ this.additionalInitializers = null;
6769
+ }
6770
+ }
6771
+ deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
6772
+ if (this.isReassigned) {
6773
+ deoptimizeInteraction(interaction);
6774
+ return;
6775
+ }
6776
+ recursionTracker.withTrackedEntityAtPath(path, this.init, () => this.init.deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker), undefined);
6777
+ }
6778
+ deoptimizePath(path) {
6779
+ if (this.isReassigned ||
6780
+ this.deoptimizationTracker.trackEntityAtPathAndGetIfTracked(path, this)) {
6781
+ return;
6782
+ }
6783
+ if (path.length === 0) {
6784
+ this.markReassigned();
6785
+ const expressionsToBeDeoptimized = this.expressionsToBeDeoptimized;
6786
+ this.expressionsToBeDeoptimized = EMPTY_ARRAY;
6787
+ for (const expression of expressionsToBeDeoptimized) {
6788
+ expression.deoptimizeCache();
6789
+ }
6790
+ this.init.deoptimizePath(UNKNOWN_PATH);
6791
+ }
6792
+ else {
6793
+ this.init.deoptimizePath(path);
6794
+ }
6795
+ }
6796
+ getLiteralValueAtPath(path, recursionTracker, origin) {
6797
+ if (this.isReassigned) {
6798
+ return UnknownValue;
6799
+ }
6800
+ return recursionTracker.withTrackedEntityAtPath(path, this.init, () => {
6801
+ this.expressionsToBeDeoptimized.push(origin);
6802
+ return this.init.getLiteralValueAtPath(path, recursionTracker, origin);
6803
+ }, UnknownValue);
6804
+ }
6805
+ getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin) {
6806
+ if (this.isReassigned) {
6807
+ return UNKNOWN_RETURN_EXPRESSION;
6808
+ }
6809
+ return recursionTracker.withTrackedEntityAtPath(path, this.init, () => {
6810
+ this.expressionsToBeDeoptimized.push(origin);
6811
+ return this.init.getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin);
6812
+ }, UNKNOWN_RETURN_EXPRESSION);
6813
+ }
6814
+ hasEffectsOnInteractionAtPath(path, interaction, context) {
6815
+ switch (interaction.type) {
6816
+ case INTERACTION_ACCESSED: {
6817
+ if (this.isReassigned)
6818
+ return true;
6819
+ return (!context.accessed.trackEntityAtPathAndGetIfTracked(path, this) &&
6820
+ this.init.hasEffectsOnInteractionAtPath(path, interaction, context));
6821
+ }
6822
+ case INTERACTION_ASSIGNED: {
6823
+ if (this.included)
6824
+ return true;
6825
+ if (path.length === 0)
6826
+ return false;
6827
+ if (this.isReassigned)
6828
+ return true;
6829
+ return (!context.assigned.trackEntityAtPathAndGetIfTracked(path, this) &&
6830
+ this.init.hasEffectsOnInteractionAtPath(path, interaction, context));
6831
+ }
6832
+ case INTERACTION_CALLED: {
6833
+ if (this.isReassigned)
6834
+ return true;
6835
+ return (!(interaction.withNew ? context.instantiated : context.called).trackEntityAtPathAndGetIfTracked(path, interaction.args, this) &&
6836
+ this.init.hasEffectsOnInteractionAtPath(path, interaction, context));
6837
+ }
6838
+ }
6839
+ }
6840
+ include() {
6841
+ if (!this.included) {
6842
+ super.include();
6843
+ for (const declaration of this.declarations) {
6844
+ // If node is a default export, it can save a tree-shaking run to include the full declaration now
6845
+ if (!declaration.included)
6846
+ declaration.include(createInclusionContext(), false);
6847
+ let node = declaration.parent;
6848
+ while (!node.included) {
6849
+ // We do not want to properly include parents in case they are part of a dead branch
6850
+ // in which case .include() might pull in more dead code
6851
+ node.included = true;
6852
+ if (node.type === Program$1)
6853
+ break;
6854
+ node = node.parent;
6855
+ }
6856
+ }
6857
+ }
6858
+ }
6859
+ includeCallArguments(context, parameters) {
6860
+ if (this.isReassigned || context.includedCallArguments.has(this.init)) {
6861
+ for (const argument of parameters) {
6862
+ argument.include(context, false);
6863
+ }
6864
+ }
6865
+ else {
6866
+ context.includedCallArguments.add(this.init);
6867
+ this.init.includeCallArguments(context, parameters);
6868
+ context.includedCallArguments.delete(this.init);
6869
+ }
6870
+ }
6871
+ markCalledFromTryStatement() {
6872
+ this.calledFromTryStatement = true;
6873
+ }
6874
+ markInitializersForDeoptimization() {
6875
+ if (this.additionalInitializers === null) {
6876
+ this.additionalInitializers = [this.init];
6877
+ this.init = UNKNOWN_EXPRESSION;
6878
+ this.markReassigned();
6879
+ }
6880
+ return this.additionalInitializers;
6881
+ }
6882
+ }
6883
+
6884
+ const tdzVariableKinds = new Set(['class', 'const', 'let', 'var', 'using', 'await using']);
6885
+ class Identifier extends NodeBase {
6886
+ constructor() {
6887
+ super(...arguments);
6888
+ this.variable = null;
6889
+ this.isReferenceVariable = false;
6890
+ }
6891
+ get isTDZAccess() {
6892
+ if (!isFlagSet(this.flags, 4 /* Flag.tdzAccessDefined */)) {
6893
+ return null;
6894
+ }
6895
+ return isFlagSet(this.flags, 8 /* Flag.tdzAccess */);
6896
+ }
6897
+ set isTDZAccess(value) {
6898
+ this.flags = setFlag(this.flags, 4 /* Flag.tdzAccessDefined */, true);
6899
+ this.flags = setFlag(this.flags, 8 /* Flag.tdzAccess */, value);
6900
+ }
6901
+ addExportedVariables(variables, exportNamesByVariable) {
6902
+ if (exportNamesByVariable.has(this.variable)) {
6903
+ variables.push(this.variable);
6904
+ }
6905
+ }
6906
+ bind() {
6907
+ if (!this.variable && is_reference(this, this.parent)) {
6908
+ this.variable = this.scope.findVariable(this.name);
6909
+ this.variable.addReference(this);
6910
+ this.isReferenceVariable = true;
6911
+ }
6912
+ }
6913
+ declare(kind, init) {
6914
+ let variable;
6915
+ const { treeshake } = this.scope.context.options;
6916
+ switch (kind) {
6917
+ case 'var': {
6918
+ variable = this.scope.addDeclaration(this, this.scope.context, init, kind);
6919
+ if (treeshake && treeshake.correctVarValueBeforeDeclaration) {
6920
+ // Necessary to make sure the init is deoptimized. We cannot call deoptimizePath here.
6921
+ variable.markInitializersForDeoptimization();
6922
+ }
6923
+ break;
6924
+ }
6925
+ case 'function': {
6926
+ // in strict mode, functions are only hoisted within a scope but not across block scopes
6927
+ variable = this.scope.addDeclaration(this, this.scope.context, init, kind);
6928
+ break;
6929
+ }
6930
+ case 'let':
6931
+ case 'const':
6932
+ case 'using':
6933
+ case 'await using':
6934
+ case 'class': {
6935
+ variable = this.scope.addDeclaration(this, this.scope.context, init, kind);
6936
+ break;
6937
+ }
6938
+ case 'parameter': {
6939
+ variable = this.scope.addParameterDeclaration(this);
6940
+ break;
6941
+ }
6942
+ /* istanbul ignore next */
6943
+ default: {
6944
+ /* istanbul ignore next */
6945
+ throw new Error(`Internal Error: Unexpected identifier kind ${kind}.`);
6946
+ }
6947
+ }
6948
+ return [(this.variable = variable)];
6949
+ }
6950
+ deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
6951
+ this.variable.deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker);
6952
+ }
6953
+ deoptimizePath(path) {
6954
+ if (path.length === 0 && !this.scope.contains(this.name)) {
6955
+ this.disallowImportReassignment();
6956
+ }
6957
+ // We keep conditional chaining because an unknown Node could have an
6958
+ // Identifier as property that might be deoptimized by default
6959
+ this.variable?.deoptimizePath(path);
6960
+ }
6961
+ getLiteralValueAtPath(path, recursionTracker, origin) {
6962
+ return this.getVariableRespectingTDZ().getLiteralValueAtPath(path, recursionTracker, origin);
6963
+ }
6964
+ getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin) {
6965
+ const [expression, isPure] = this.getVariableRespectingTDZ().getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin);
6966
+ return [expression, isPure || this.isPureFunction(path)];
6967
+ }
6968
+ hasEffects(context) {
6969
+ if (!this.deoptimized)
6970
+ this.applyDeoptimizations();
6971
+ if (this.isPossibleTDZ() && this.variable.kind !== 'var') {
6972
+ return true;
6973
+ }
6974
+ return (this.scope.context.options.treeshake
6975
+ .unknownGlobalSideEffects &&
6976
+ this.variable instanceof GlobalVariable &&
6977
+ !this.isPureFunction(EMPTY_PATH) &&
6978
+ this.variable.hasEffectsOnInteractionAtPath(EMPTY_PATH, NODE_INTERACTION_UNKNOWN_ACCESS, context));
6979
+ }
6980
+ hasEffectsOnInteractionAtPath(path, interaction, context) {
6981
+ switch (interaction.type) {
6982
+ case INTERACTION_ACCESSED: {
6983
+ return (this.variable !== null &&
6984
+ !this.isPureFunction(path) &&
6985
+ this.getVariableRespectingTDZ().hasEffectsOnInteractionAtPath(path, interaction, context));
6986
+ }
6987
+ case INTERACTION_ASSIGNED: {
6988
+ return (path.length > 0 ? this.getVariableRespectingTDZ() : this.variable).hasEffectsOnInteractionAtPath(path, interaction, context);
6989
+ }
6990
+ case INTERACTION_CALLED: {
6991
+ return (!this.isPureFunction(path) &&
6992
+ this.getVariableRespectingTDZ().hasEffectsOnInteractionAtPath(path, interaction, context));
6993
+ }
6994
+ }
6995
+ }
6996
+ include() {
6997
+ if (!this.deoptimized)
6998
+ this.applyDeoptimizations();
6999
+ if (!this.included) {
7000
+ this.included = true;
7001
+ if (this.variable !== null) {
7002
+ this.scope.context.includeVariableInModule(this.variable);
7003
+ }
7004
+ }
7005
+ }
7006
+ includeCallArguments(context, parameters) {
7007
+ this.variable.includeCallArguments(context, parameters);
7008
+ }
7009
+ isPossibleTDZ() {
7010
+ // return cached value to avoid issues with the next tree-shaking pass
7011
+ const cachedTdzAccess = this.isTDZAccess;
7012
+ if (cachedTdzAccess !== null)
7013
+ return cachedTdzAccess;
7014
+ if (!(this.variable instanceof LocalVariable &&
7015
+ this.variable.kind &&
7016
+ tdzVariableKinds.has(this.variable.kind) &&
7017
+ // we ignore possible TDZs due to circular module dependencies as
7018
+ // otherwise we get many false positives
7019
+ this.variable.module === this.scope.context.module)) {
7020
+ return (this.isTDZAccess = false);
7021
+ }
7022
+ let decl_id;
7023
+ if (this.variable.declarations &&
7024
+ this.variable.declarations.length === 1 &&
7025
+ (decl_id = this.variable.declarations[0]) &&
7026
+ this.start < decl_id.start &&
7027
+ closestParentFunctionOrProgram(this) === closestParentFunctionOrProgram(decl_id)) {
7028
+ // a variable accessed before its declaration
7029
+ // in the same function or at top level of module
7030
+ return (this.isTDZAccess = true);
7031
+ }
7032
+ // We ignore the case where the module is not yet executed because
7033
+ // moduleSideEffects are false.
7034
+ if (!this.variable.initReached && this.scope.context.module.isExecuted) {
7035
+ // Either a const/let TDZ violation or
7036
+ // var use before declaration was encountered.
7037
+ return (this.isTDZAccess = true);
7038
+ }
7039
+ return (this.isTDZAccess = false);
7040
+ }
7041
+ markDeclarationReached() {
7042
+ this.variable.initReached = true;
7043
+ }
7044
+ render(code, { snippets: { getPropertyAccess }, useOriginalName }, { renderedParentType, isCalleeOfRenderedParent, isShorthandProperty } = BLANK) {
7045
+ if (this.variable) {
7046
+ const name = this.variable.getName(getPropertyAccess, useOriginalName);
7047
+ if (name !== this.name) {
7048
+ code.overwrite(this.start, this.end, name, {
7049
+ contentOnly: true,
7050
+ storeName: true
7051
+ });
7052
+ if (isShorthandProperty) {
7053
+ code.prependRight(this.start, `${this.name}: `);
7054
+ }
7055
+ }
7056
+ // In strict mode, any variable named "eval" must be the actual "eval" function
7057
+ if (name === 'eval' &&
7058
+ renderedParentType === CallExpression$1 &&
7059
+ isCalleeOfRenderedParent) {
7060
+ code.appendRight(this.start, '0, ');
7061
+ }
7062
+ }
7063
+ }
7064
+ disallowImportReassignment() {
7065
+ return this.scope.context.error(logIllegalImportReassignment(this.name, this.scope.context.module.id), this.start);
7066
+ }
7067
+ applyDeoptimizations() {
7068
+ this.deoptimized = true;
7069
+ if (this.variable instanceof LocalVariable) {
7070
+ this.variable.consolidateInitializers();
7071
+ this.scope.context.requestTreeshakingPass();
7072
+ }
7073
+ if (this.isReferenceVariable) {
7074
+ this.variable.addUsedPlace(this);
7075
+ this.scope.context.requestTreeshakingPass();
7076
+ }
7077
+ }
7078
+ getVariableRespectingTDZ() {
7079
+ if (this.isPossibleTDZ()) {
7080
+ return UNKNOWN_EXPRESSION;
7081
+ }
7082
+ return this.variable;
7083
+ }
7084
+ isPureFunction(path) {
7085
+ let currentPureFunction = this.scope.context.manualPureFunctions[this.name];
7086
+ for (const segment of path) {
7087
+ if (currentPureFunction) {
7088
+ if (currentPureFunction[PureFunctionKey]) {
7089
+ return true;
7090
+ }
7091
+ currentPureFunction = currentPureFunction[segment];
7092
+ }
7093
+ else {
7094
+ return false;
7095
+ }
7096
+ }
7097
+ return currentPureFunction?.[PureFunctionKey];
7098
+ }
7099
+ }
7100
+ function closestParentFunctionOrProgram(node) {
7101
+ while (node && !/^Program|Function/.test(node.type)) {
7102
+ node = node.parent;
7103
+ }
7104
+ // one of: ArrowFunctionExpression, FunctionDeclaration, FunctionExpression or Program
7105
+ return node;
7106
+ }
7107
+
7108
+ const MAX_TRACKED_INTERACTIONS = 20;
7109
+ const NO_INTERACTIONS = EMPTY_ARRAY;
7110
+ const UNKNOWN_DEOPTIMIZED_FIELD = new Set([UnknownKey]);
7111
+ const EMPTY_PATH_TRACKER = new PathTracker();
7112
+ const UNKNOWN_DEOPTIMIZED_ENTITY = new Set([UNKNOWN_EXPRESSION]);
7113
+ class ParameterVariable extends LocalVariable {
7114
+ constructor(name, declarator, context) {
7115
+ super(name, declarator, UNKNOWN_EXPRESSION, context, 'parameter');
7116
+ this.deoptimizationInteractions = [];
7117
+ this.deoptimizations = new PathTracker();
7118
+ this.deoptimizedFields = new Set();
7119
+ this.entitiesToBeDeoptimized = new Set();
7120
+ this.expressionsUseTheKnownValue = [];
7121
+ this.knownValue = null;
7122
+ this.knownValueLiteral = UnknownValue;
7123
+ this.frozenValue = null;
7124
+ }
7125
+ addEntityToBeDeoptimized(entity) {
7126
+ if (entity === UNKNOWN_EXPRESSION) {
7127
+ // As unknown expressions fully deoptimize all interactions, we can clear
7128
+ // the interaction cache at this point provided we keep this optimization
7129
+ // in mind when adding new interactions
7130
+ if (!this.entitiesToBeDeoptimized.has(UNKNOWN_EXPRESSION)) {
7131
+ this.entitiesToBeDeoptimized.add(UNKNOWN_EXPRESSION);
7132
+ for (const { interaction } of this.deoptimizationInteractions) {
7133
+ deoptimizeInteraction(interaction);
7134
+ }
7135
+ this.deoptimizationInteractions = NO_INTERACTIONS;
7136
+ }
7137
+ }
7138
+ else if (this.deoptimizedFields.has(UnknownKey)) {
7139
+ // This means that we already deoptimized all interactions and no longer
7140
+ // track them
7141
+ entity.deoptimizePath(UNKNOWN_PATH);
7142
+ }
7143
+ else if (!this.entitiesToBeDeoptimized.has(entity)) {
7144
+ this.entitiesToBeDeoptimized.add(entity);
7145
+ for (const field of this.deoptimizedFields) {
7146
+ entity.deoptimizePath([field]);
7147
+ }
7148
+ for (const { interaction, path } of this.deoptimizationInteractions) {
7149
+ entity.deoptimizeArgumentsOnInteractionAtPath(interaction, path, SHARED_RECURSION_TRACKER);
7150
+ }
7151
+ }
7152
+ }
7153
+ markReassigned() {
7154
+ if (this.isReassigned) {
7155
+ return;
7156
+ }
7157
+ super.markReassigned();
7158
+ for (const expression of this.expressionsUseTheKnownValue) {
7159
+ expression.deoptimizeCache();
7160
+ }
7161
+ this.expressionsUseTheKnownValue = EMPTY_ARRAY;
7162
+ }
7163
+ deoptimizeCache() {
7164
+ this.markReassigned();
7165
+ }
7166
+ /**
7167
+ * Update the known value of the parameter variable.
7168
+ * Must be called for every function call, so it can track all the arguments,
7169
+ * and deoptimizeCache itself to mark reassigned if the argument is changed.
7170
+ * @param argument The argument of the function call
7171
+ */
7172
+ updateKnownValue(argument) {
7173
+ if (this.isReassigned) {
7174
+ return;
7175
+ }
7176
+ if (this.knownValue === null) {
7177
+ this.knownValue = argument;
7178
+ this.knownValueLiteral = argument.getLiteralValueAtPath(EMPTY_PATH, SHARED_RECURSION_TRACKER, this);
7179
+ return;
7180
+ }
7181
+ // the same literal or identifier, do nothing
7182
+ if (this.knownValue === argument ||
7183
+ (this.knownValue instanceof Identifier &&
7184
+ argument instanceof Identifier &&
7185
+ this.knownValue.variable === argument.variable)) {
7186
+ return;
7187
+ }
7188
+ const oldValue = this.knownValueLiteral;
7189
+ if (typeof oldValue === 'symbol') {
7190
+ this.markReassigned();
7191
+ return;
7192
+ }
7193
+ // add tracking for the new argument
7194
+ const newValue = argument.getLiteralValueAtPath(EMPTY_PATH, SHARED_RECURSION_TRACKER, this);
7195
+ if (newValue !== oldValue) {
7196
+ this.markReassigned();
7197
+ }
7198
+ }
7199
+ /**
7200
+ * This function freezes the known value of the parameter variable,
7201
+ * so the optimization starts with a certain ExpressionEntity.
7202
+ * The optimization can be undone by calling `markReassigned`.
7203
+ * @returns the frozen value
7204
+ */
7205
+ getKnownValue() {
7206
+ if (this.frozenValue === null) {
7207
+ this.frozenValue = this.knownValue || UNKNOWN_EXPRESSION;
7208
+ }
7209
+ return this.frozenValue;
7210
+ }
7211
+ getLiteralValueAtPath(path, recursionTracker, origin) {
7212
+ if (this.isReassigned) {
7213
+ return UnknownValue;
7214
+ }
7215
+ const knownValue = this.getKnownValue();
7216
+ this.expressionsUseTheKnownValue.push(origin);
7217
+ return recursionTracker.withTrackedEntityAtPath(path, knownValue, () => knownValue.getLiteralValueAtPath(path, recursionTracker, origin), UnknownValue);
7218
+ }
7219
+ hasEffectsOnInteractionAtPath(path, interaction, context) {
7220
+ if (this.isReassigned || interaction.type === INTERACTION_ASSIGNED) {
7221
+ return super.hasEffectsOnInteractionAtPath(path, interaction, context);
7222
+ }
7223
+ const knownValue = this.getKnownValue();
7224
+ return knownValue.hasEffectsOnInteractionAtPath(path, interaction, context);
7225
+ }
7226
+ deoptimizeArgumentsOnInteractionAtPath(interaction, path) {
7227
+ // For performance reasons, we fully deoptimize all deeper interactions
7228
+ if (path.length >= 2 ||
7229
+ this.entitiesToBeDeoptimized.has(UNKNOWN_EXPRESSION) ||
7230
+ this.deoptimizationInteractions.length >= MAX_TRACKED_INTERACTIONS ||
7231
+ (path.length === 1 &&
7232
+ (this.deoptimizedFields.has(UnknownKey) ||
7233
+ (interaction.type === INTERACTION_CALLED && this.deoptimizedFields.has(path[0]))))) {
7234
+ deoptimizeInteraction(interaction);
7235
+ return;
7236
+ }
7237
+ if (!this.deoptimizations.trackEntityAtPathAndGetIfTracked(path, interaction.args)) {
7238
+ for (const entity of this.entitiesToBeDeoptimized) {
7239
+ entity.deoptimizeArgumentsOnInteractionAtPath(interaction, path, SHARED_RECURSION_TRACKER);
7240
+ }
7241
+ if (!this.entitiesToBeDeoptimized.has(UNKNOWN_EXPRESSION)) {
7242
+ this.deoptimizationInteractions.push({
7243
+ interaction,
7244
+ path
7245
+ });
7246
+ }
7247
+ }
7248
+ }
7249
+ deoptimizePath(path) {
7250
+ if (path.length === 0) {
7251
+ this.markReassigned();
7252
+ return;
7253
+ }
7254
+ if (this.deoptimizedFields.has(UnknownKey)) {
7255
+ return;
7256
+ }
7257
+ const key = path[0];
7258
+ if (this.deoptimizedFields.has(key)) {
7259
+ return;
7260
+ }
7261
+ this.deoptimizedFields.add(key);
7262
+ for (const entity of this.entitiesToBeDeoptimized) {
7263
+ // We do not need a recursion tracker here as we already track whether
7264
+ // this field is deoptimized
7265
+ entity.deoptimizePath([key]);
7266
+ }
7267
+ if (key === UnknownKey) {
7268
+ // save some memory
7269
+ this.deoptimizationInteractions = NO_INTERACTIONS;
7270
+ this.deoptimizations = EMPTY_PATH_TRACKER;
7271
+ this.deoptimizedFields = UNKNOWN_DEOPTIMIZED_FIELD;
7272
+ this.entitiesToBeDeoptimized = UNKNOWN_DEOPTIMIZED_ENTITY;
7273
+ }
7274
+ }
7275
+ getReturnExpressionWhenCalledAtPath(path) {
7276
+ // We deoptimize everything that is called as that will trivially deoptimize
7277
+ // the corresponding return expressions as well and avoid badly performing
7278
+ // and complicated alternatives
7279
+ if (path.length === 0) {
7280
+ this.deoptimizePath(UNKNOWN_PATH);
7281
+ }
7282
+ else if (!this.deoptimizedFields.has(path[0])) {
7283
+ this.deoptimizePath([path[0]]);
7284
+ }
7285
+ return UNKNOWN_RETURN_EXPRESSION;
7286
+ }
7287
+ }
7288
+
7289
+ const chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_$';
7290
+ const base = 64;
7291
+ function toBase64(value) {
7292
+ let outString = '';
7293
+ do {
7294
+ const currentDigit = value % base;
7295
+ value = (value / base) | 0;
7296
+ outString = chars[currentDigit] + outString;
7297
+ } while (value !== 0);
7298
+ return outString;
7299
+ }
7300
+
7301
+ function getSafeName(baseName, usedNames, forbiddenNames) {
7302
+ let safeName = baseName;
7303
+ let count = 1;
7304
+ while (usedNames.has(safeName) || RESERVED_NAMES.has(safeName) || forbiddenNames?.has(safeName)) {
7305
+ safeName = `${baseName}$${toBase64(count++)}`;
7306
+ }
7307
+ usedNames.add(safeName);
7308
+ return safeName;
7309
+ }
7310
+
7311
+ class Scope {
7312
+ constructor() {
7313
+ this.children = [];
7314
+ this.variables = new Map();
7315
+ }
7316
+ /*
7317
+ Redeclaration rules:
7318
+ - var can redeclare var
7319
+ - in function scopes, function and var can redeclare function and var
7320
+ - var is hoisted across scopes, function remains in the scope it is declared
7321
+ - var and function can redeclare function parameters, but parameters cannot redeclare parameters
7322
+ - function cannot redeclare catch scope parameters
7323
+ - var can redeclare catch scope parameters in a way
7324
+ - if the parameter is an identifier and not a pattern
7325
+ - then the variable is still declared in the hoisted outer scope, but the initializer is assigned to the parameter
7326
+ - const, let, class, and function except in the cases above cannot redeclare anything
7327
+ */
7328
+ addDeclaration(identifier, context, init, kind) {
7329
+ const name = identifier.name;
7330
+ const existingVariable = this.hoistedVariables?.get(name) || this.variables.get(name);
7331
+ if (existingVariable) {
7332
+ const existingKind = existingVariable.kind;
7333
+ if (kind === 'var' && existingKind === 'var') {
7334
+ existingVariable.addDeclaration(identifier, init);
7335
+ return existingVariable;
7336
+ }
7337
+ context.error(logRedeclarationError(name), identifier.start);
7338
+ }
7339
+ const newVariable = new LocalVariable(identifier.name, identifier, init, context, kind);
7340
+ this.variables.set(name, newVariable);
7341
+ return newVariable;
7342
+ }
7343
+ addHoistedVariable(name, variable) {
7344
+ (this.hoistedVariables ||= new Map()).set(name, variable);
7345
+ }
7346
+ contains(name) {
7347
+ return this.variables.has(name);
7348
+ }
7349
+ findVariable(_name) {
7350
+ /* istanbul ignore next */
7351
+ throw new Error('Internal Error: findVariable needs to be implemented by a subclass');
7352
+ }
7353
+ }
7354
+
7355
+ class ChildScope extends Scope {
7356
+ constructor(parent, context) {
7357
+ super();
7358
+ this.parent = parent;
7359
+ this.context = context;
7360
+ this.accessedOutsideVariables = new Map();
7361
+ parent.children.push(this);
7362
+ }
7363
+ addAccessedDynamicImport(importExpression) {
7364
+ (this.accessedDynamicImports || (this.accessedDynamicImports = new Set())).add(importExpression);
7365
+ if (this.parent instanceof ChildScope) {
7366
+ this.parent.addAccessedDynamicImport(importExpression);
7295
7367
  }
7296
- currentGlobal = currentGlobal[pathSegment];
7297
- if (!currentGlobal) {
7298
- return null;
7368
+ }
7369
+ addAccessedGlobals(globals, accessedGlobalsByScope) {
7370
+ const accessedGlobals = accessedGlobalsByScope.get(this) || new Set();
7371
+ for (const name of globals) {
7372
+ accessedGlobals.add(name);
7373
+ }
7374
+ accessedGlobalsByScope.set(this, accessedGlobals);
7375
+ if (this.parent instanceof ChildScope) {
7376
+ this.parent.addAccessedGlobals(globals, accessedGlobalsByScope);
7299
7377
  }
7300
7378
  }
7301
- return currentGlobal[ValueProperties];
7302
- }
7303
-
7304
- class GlobalVariable extends Variable {
7305
- constructor(name) {
7306
- super(name);
7307
- // Ensure we use live-bindings for globals as we do not know if they have
7308
- // been reassigned
7309
- this.markReassigned();
7379
+ addNamespaceMemberAccess(name, variable) {
7380
+ this.accessedOutsideVariables.set(name, variable);
7381
+ this.parent.addNamespaceMemberAccess(name, variable);
7310
7382
  }
7311
- deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
7312
- switch (interaction.type) {
7313
- // While there is no point in testing these cases as at the moment, they
7314
- // are also covered via other means, we keep them for completeness
7315
- case INTERACTION_ACCESSED:
7316
- case INTERACTION_ASSIGNED: {
7317
- if (!getGlobalAtPath([this.name, ...path].slice(0, -1))) {
7318
- super.deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker);
7383
+ addReturnExpression(expression) {
7384
+ this.parent instanceof ChildScope && this.parent.addReturnExpression(expression);
7385
+ }
7386
+ addUsedOutsideNames(usedNames, format, exportNamesByVariable, accessedGlobalsByScope) {
7387
+ for (const variable of this.accessedOutsideVariables.values()) {
7388
+ if (variable.included) {
7389
+ usedNames.add(variable.getBaseVariableName());
7390
+ if (format === 'system' && exportNamesByVariable.has(variable)) {
7391
+ usedNames.add('exports');
7319
7392
  }
7320
- return;
7321
7393
  }
7322
- case INTERACTION_CALLED: {
7323
- const globalAtPath = getGlobalAtPath([this.name, ...path]);
7324
- if (globalAtPath) {
7325
- globalAtPath.deoptimizeArgumentsOnCall(interaction);
7326
- }
7327
- else {
7328
- super.deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker);
7329
- }
7330
- return;
7394
+ }
7395
+ const accessedGlobals = accessedGlobalsByScope.get(this);
7396
+ if (accessedGlobals) {
7397
+ for (const name of accessedGlobals) {
7398
+ usedNames.add(name);
7331
7399
  }
7332
7400
  }
7333
7401
  }
7334
- getLiteralValueAtPath(path, _recursionTracker, _origin) {
7335
- const globalAtPath = getGlobalAtPath([this.name, ...path]);
7336
- return globalAtPath ? globalAtPath.getLiteralValue() : UnknownValue;
7402
+ contains(name) {
7403
+ return this.variables.has(name) || this.parent.contains(name);
7337
7404
  }
7338
- hasEffectsOnInteractionAtPath(path, interaction, context) {
7339
- switch (interaction.type) {
7340
- case INTERACTION_ACCESSED: {
7341
- if (path.length === 0) {
7342
- // Technically, "undefined" is a global variable of sorts
7343
- return this.name !== 'undefined' && !getGlobalAtPath([this.name]);
7405
+ deconflict(format, exportNamesByVariable, accessedGlobalsByScope) {
7406
+ const usedNames = new Set();
7407
+ this.addUsedOutsideNames(usedNames, format, exportNamesByVariable, accessedGlobalsByScope);
7408
+ if (this.accessedDynamicImports) {
7409
+ for (const importExpression of this.accessedDynamicImports) {
7410
+ if (importExpression.inlineNamespace) {
7411
+ usedNames.add(importExpression.inlineNamespace.getBaseVariableName());
7344
7412
  }
7345
- return !getGlobalAtPath([this.name, ...path].slice(0, -1));
7346
- }
7347
- case INTERACTION_ASSIGNED: {
7348
- return true;
7349
7413
  }
7350
- case INTERACTION_CALLED: {
7351
- const globalAtPath = getGlobalAtPath([this.name, ...path]);
7352
- return !globalAtPath || globalAtPath.hasEffectsWhenCalled(interaction, context);
7414
+ }
7415
+ for (const [name, variable] of this.variables) {
7416
+ if (variable.included || variable.alwaysRendered) {
7417
+ variable.setRenderNames(null, getSafeName(name, usedNames, variable.forbiddenNames));
7353
7418
  }
7354
7419
  }
7355
- }
7356
- }
7357
-
7358
- const tdzVariableKinds = new Set(['class', 'const', 'let', 'var', 'using', 'await using']);
7359
- class Identifier extends NodeBase {
7360
- constructor() {
7361
- super(...arguments);
7362
- this.variable = null;
7363
- this.isReferenceVariable = false;
7364
- }
7365
- get isTDZAccess() {
7366
- if (!isFlagSet(this.flags, 4 /* Flag.tdzAccessDefined */)) {
7367
- return null;
7420
+ for (const scope of this.children) {
7421
+ scope.deconflict(format, exportNamesByVariable, accessedGlobalsByScope);
7368
7422
  }
7369
- return isFlagSet(this.flags, 8 /* Flag.tdzAccess */);
7370
7423
  }
7371
- set isTDZAccess(value) {
7372
- this.flags = setFlag(this.flags, 4 /* Flag.tdzAccessDefined */, true);
7373
- this.flags = setFlag(this.flags, 8 /* Flag.tdzAccess */, value);
7424
+ findLexicalBoundary() {
7425
+ return this.parent.findLexicalBoundary();
7374
7426
  }
7375
- addExportedVariables(variables, exportNamesByVariable) {
7376
- if (exportNamesByVariable.has(this.variable)) {
7377
- variables.push(this.variable);
7427
+ findVariable(name) {
7428
+ const knownVariable = this.variables.get(name) || this.accessedOutsideVariables.get(name);
7429
+ if (knownVariable) {
7430
+ return knownVariable;
7378
7431
  }
7432
+ const variable = this.parent.findVariable(name);
7433
+ this.accessedOutsideVariables.set(name, variable);
7434
+ return variable;
7379
7435
  }
7380
- bind() {
7381
- if (!this.variable && is_reference(this, this.parent)) {
7382
- this.variable = this.scope.findVariable(this.name);
7383
- this.variable.addReference(this);
7384
- this.isReferenceVariable = true;
7385
- }
7436
+ }
7437
+
7438
+ class CatchBodyScope extends ChildScope {
7439
+ constructor(parent) {
7440
+ super(parent, parent.context);
7441
+ this.parent = parent;
7386
7442
  }
7387
- declare(kind, init) {
7388
- let variable;
7389
- const { treeshake } = this.scope.context.options;
7390
- switch (kind) {
7391
- case 'var': {
7392
- variable = this.scope.addDeclaration(this, this.scope.context, init, kind);
7393
- if (treeshake && treeshake.correctVarValueBeforeDeclaration) {
7394
- // Necessary to make sure the init is deoptimized. We cannot call deoptimizePath here.
7395
- variable.markInitializersForDeoptimization();
7443
+ addDeclaration(identifier, context, init, kind) {
7444
+ if (kind === 'var') {
7445
+ const name = identifier.name;
7446
+ const existingVariable = this.hoistedVariables?.get(name) || this.variables.get(name);
7447
+ if (existingVariable) {
7448
+ const existingKind = existingVariable.kind;
7449
+ if (existingKind === 'parameter' &&
7450
+ // If this is a destructured parameter, it is forbidden to redeclare
7451
+ existingVariable.declarations[0].parent.type === CatchClause$1) {
7452
+ // If this is a var with the same name as the catch scope parameter,
7453
+ // the assignment actually goes to the parameter and the var is
7454
+ // hoisted without assignment. Locally, it is shadowed by the
7455
+ // parameter
7456
+ const declaredVariable = this.parent.parent.addDeclaration(identifier, context, UNDEFINED_EXPRESSION, kind);
7457
+ // To avoid the need to rewrite the declaration, we link the variable
7458
+ // names. If we ever implement a logic that splits initialization and
7459
+ // assignment for hoisted vars, the "renderLikeHoisted" logic can be
7460
+ // removed again.
7461
+ // We do not need to check whether there already is a linked
7462
+ // variable because then declaredVariable would be that linked
7463
+ // variable.
7464
+ existingVariable.renderLikeHoisted(declaredVariable);
7465
+ this.addHoistedVariable(name, declaredVariable);
7466
+ return declaredVariable;
7396
7467
  }
7397
- break;
7398
- }
7399
- case 'function': {
7400
- // in strict mode, functions are only hoisted within a scope but not across block scopes
7401
- variable = this.scope.addDeclaration(this, this.scope.context, init, kind);
7402
- break;
7403
- }
7404
- case 'let':
7405
- case 'const':
7406
- case 'using':
7407
- case 'await using':
7408
- case 'class': {
7409
- variable = this.scope.addDeclaration(this, this.scope.context, init, kind);
7410
- break;
7411
- }
7412
- case 'parameter': {
7413
- variable = this.scope.addParameterDeclaration(this);
7414
- break;
7415
- }
7416
- /* istanbul ignore next */
7417
- default: {
7418
- /* istanbul ignore next */
7419
- throw new Error(`Internal Error: Unexpected identifier kind ${kind}.`);
7468
+ if (existingKind === 'var') {
7469
+ existingVariable.addDeclaration(identifier, init);
7470
+ return existingVariable;
7471
+ }
7472
+ return context.error(logRedeclarationError(name), identifier.start);
7420
7473
  }
7474
+ // We only add parameters to parameter scopes
7475
+ const declaredVariable = this.parent.parent.addDeclaration(identifier, context, init, kind);
7476
+ // Necessary to make sure the init is deoptimized for conditional declarations.
7477
+ // We cannot call deoptimizePath here.
7478
+ declaredVariable.markInitializersForDeoptimization();
7479
+ // We add the variable to this and all parent scopes to reliably detect conflicts
7480
+ this.addHoistedVariable(name, declaredVariable);
7481
+ return declaredVariable;
7421
7482
  }
7422
- return [(this.variable = variable)];
7483
+ return super.addDeclaration(identifier, context, init, kind);
7423
7484
  }
7424
- deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
7425
- this.variable.deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker);
7485
+ }
7486
+
7487
+ class FunctionBodyScope extends ChildScope {
7488
+ constructor(parent) {
7489
+ super(parent, parent.context);
7426
7490
  }
7427
- deoptimizePath(path) {
7428
- if (path.length === 0 && !this.scope.contains(this.name)) {
7429
- this.disallowImportReassignment();
7491
+ // There is stuff that is only allowed in function scopes, i.e. functions can
7492
+ // be redeclared, functions and var can redeclare each other
7493
+ addDeclaration(identifier, context, init, kind) {
7494
+ const name = identifier.name;
7495
+ const existingVariable = this.hoistedVariables?.get(name) || this.variables.get(name);
7496
+ if (existingVariable) {
7497
+ const existingKind = existingVariable.kind;
7498
+ if ((kind === 'var' || kind === 'function') &&
7499
+ (existingKind === 'var' || existingKind === 'function' || existingKind === 'parameter')) {
7500
+ existingVariable.addDeclaration(identifier, init);
7501
+ return existingVariable;
7502
+ }
7503
+ context.error(logRedeclarationError(name), identifier.start);
7430
7504
  }
7431
- // We keep conditional chaining because an unknown Node could have an
7432
- // Identifier as property that might be deoptimized by default
7433
- this.variable?.deoptimizePath(path);
7434
- }
7435
- getLiteralValueAtPath(path, recursionTracker, origin) {
7436
- return this.getVariableRespectingTDZ().getLiteralValueAtPath(path, recursionTracker, origin);
7437
- }
7438
- getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin) {
7439
- const [expression, isPure] = this.getVariableRespectingTDZ().getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin);
7440
- return [expression, isPure || this.isPureFunction(path)];
7505
+ const newVariable = new LocalVariable(identifier.name, identifier, init, context, kind);
7506
+ this.variables.set(name, newVariable);
7507
+ return newVariable;
7441
7508
  }
7442
- hasEffects(context) {
7443
- if (!this.deoptimized)
7444
- this.applyDeoptimizations();
7445
- if (this.isPossibleTDZ() && this.variable.kind !== 'var') {
7446
- return true;
7447
- }
7448
- return (this.scope.context.options.treeshake
7449
- .unknownGlobalSideEffects &&
7450
- this.variable instanceof GlobalVariable &&
7451
- !this.isPureFunction(EMPTY_PATH) &&
7452
- this.variable.hasEffectsOnInteractionAtPath(EMPTY_PATH, NODE_INTERACTION_UNKNOWN_ACCESS, context));
7509
+ }
7510
+
7511
+ class ParameterScope extends ChildScope {
7512
+ constructor(parent, isCatchScope) {
7513
+ super(parent, parent.context);
7514
+ this.parameters = [];
7515
+ this.hasRest = false;
7516
+ this.bodyScope = isCatchScope ? new CatchBodyScope(this) : new FunctionBodyScope(this);
7453
7517
  }
7454
- hasEffectsOnInteractionAtPath(path, interaction, context) {
7455
- switch (interaction.type) {
7456
- case INTERACTION_ACCESSED: {
7457
- return (this.variable !== null &&
7458
- !this.isPureFunction(path) &&
7459
- this.getVariableRespectingTDZ().hasEffectsOnInteractionAtPath(path, interaction, context));
7460
- }
7461
- case INTERACTION_ASSIGNED: {
7462
- return (path.length > 0 ? this.getVariableRespectingTDZ() : this.variable).hasEffectsOnInteractionAtPath(path, interaction, context);
7463
- }
7464
- case INTERACTION_CALLED: {
7465
- return (!this.isPureFunction(path) &&
7466
- this.getVariableRespectingTDZ().hasEffectsOnInteractionAtPath(path, interaction, context));
7467
- }
7518
+ /**
7519
+ * Adds a parameter to this scope. Parameters must be added in the correct
7520
+ * order, i.e. from left to right.
7521
+ */
7522
+ addParameterDeclaration(identifier) {
7523
+ const { name, start } = identifier;
7524
+ const existingParameter = this.variables.get(name);
7525
+ if (existingParameter) {
7526
+ return this.context.error(logDuplicateArgumentNameError(name), start);
7468
7527
  }
7528
+ const variable = new ParameterVariable(name, identifier, this.context);
7529
+ this.variables.set(name, variable);
7530
+ // We also add it to the body scope to detect name conflicts with local
7531
+ // variables. We still need the intermediate scope, though, as parameter
7532
+ // defaults are NOT taken from the body scope but from the parameters or
7533
+ // outside scope.
7534
+ this.bodyScope.addHoistedVariable(name, variable);
7535
+ return variable;
7469
7536
  }
7470
- include() {
7471
- if (!this.deoptimized)
7472
- this.applyDeoptimizations();
7473
- if (!this.included) {
7474
- this.included = true;
7475
- if (this.variable !== null) {
7476
- this.scope.context.includeVariableInModule(this.variable);
7537
+ addParameterVariables(parameters, hasRest) {
7538
+ this.parameters = parameters;
7539
+ for (const parameterList of parameters) {
7540
+ for (const parameter of parameterList) {
7541
+ parameter.alwaysRendered = true;
7477
7542
  }
7478
7543
  }
7544
+ this.hasRest = hasRest;
7479
7545
  }
7480
7546
  includeCallArguments(context, parameters) {
7481
- this.variable.includeCallArguments(context, parameters);
7482
- }
7483
- isPossibleTDZ() {
7484
- // return cached value to avoid issues with the next tree-shaking pass
7485
- const cachedTdzAccess = this.isTDZAccess;
7486
- if (cachedTdzAccess !== null)
7487
- return cachedTdzAccess;
7488
- if (!(this.variable instanceof LocalVariable &&
7489
- this.variable.kind &&
7490
- tdzVariableKinds.has(this.variable.kind) &&
7491
- // we ignore possible TDZs due to circular module dependencies as
7492
- // otherwise we get many false positives
7493
- this.variable.module === this.scope.context.module)) {
7494
- return (this.isTDZAccess = false);
7495
- }
7496
- let decl_id;
7497
- if (this.variable.declarations &&
7498
- this.variable.declarations.length === 1 &&
7499
- (decl_id = this.variable.declarations[0]) &&
7500
- this.start < decl_id.start &&
7501
- closestParentFunctionOrProgram(this) === closestParentFunctionOrProgram(decl_id)) {
7502
- // a variable accessed before its declaration
7503
- // in the same function or at top level of module
7504
- return (this.isTDZAccess = true);
7505
- }
7506
- // We ignore the case where the module is not yet executed because
7507
- // moduleSideEffects are false.
7508
- if (!this.variable.initReached && this.scope.context.module.isExecuted) {
7509
- // Either a const/let TDZ violation or
7510
- // var use before declaration was encountered.
7511
- return (this.isTDZAccess = true);
7547
+ let calledFromTryStatement = false;
7548
+ let argumentIncluded = false;
7549
+ const restParameter = this.hasRest && this.parameters[this.parameters.length - 1];
7550
+ for (const checkedArgument of parameters) {
7551
+ if (checkedArgument instanceof SpreadElement) {
7552
+ for (const argument of parameters) {
7553
+ argument.include(context, false);
7554
+ }
7555
+ break;
7556
+ }
7512
7557
  }
7513
- return (this.isTDZAccess = false);
7514
- }
7515
- markDeclarationReached() {
7516
- this.variable.initReached = true;
7517
- }
7518
- render(code, { snippets: { getPropertyAccess }, useOriginalName }, { renderedParentType, isCalleeOfRenderedParent, isShorthandProperty } = BLANK) {
7519
- if (this.variable) {
7520
- const name = this.variable.getName(getPropertyAccess, useOriginalName);
7521
- if (name !== this.name) {
7522
- code.overwrite(this.start, this.end, name, {
7523
- contentOnly: true,
7524
- storeName: true
7525
- });
7526
- if (isShorthandProperty) {
7527
- code.prependRight(this.start, `${this.name}: `);
7558
+ for (let index = parameters.length - 1; index >= 0; index--) {
7559
+ const parameterVariables = this.parameters[index] || restParameter;
7560
+ const argument = parameters[index];
7561
+ if (parameterVariables) {
7562
+ calledFromTryStatement = false;
7563
+ if (parameterVariables.length === 0) {
7564
+ // handle empty destructuring
7565
+ argumentIncluded = true;
7566
+ }
7567
+ else {
7568
+ for (const variable of parameterVariables) {
7569
+ if (variable.included) {
7570
+ argumentIncluded = true;
7571
+ }
7572
+ if (variable.calledFromTryStatement) {
7573
+ calledFromTryStatement = true;
7574
+ }
7575
+ }
7528
7576
  }
7529
7577
  }
7530
- // In strict mode, any variable named "eval" must be the actual "eval" function
7531
- if (name === 'eval' &&
7532
- renderedParentType === CallExpression$1 &&
7533
- isCalleeOfRenderedParent) {
7534
- code.appendRight(this.start, '0, ');
7578
+ if (!argumentIncluded && argument.shouldBeIncluded(context)) {
7579
+ argumentIncluded = true;
7580
+ }
7581
+ if (argumentIncluded) {
7582
+ argument.include(context, calledFromTryStatement);
7535
7583
  }
7536
7584
  }
7537
7585
  }
7538
- disallowImportReassignment() {
7539
- return this.scope.context.error(logIllegalImportReassignment(this.name, this.scope.context.module.id), this.start);
7586
+ }
7587
+
7588
+ class ReturnValueScope extends ParameterScope {
7589
+ constructor() {
7590
+ super(...arguments);
7591
+ this.returnExpression = null;
7592
+ this.returnExpressions = [];
7540
7593
  }
7541
- applyDeoptimizations() {
7542
- this.deoptimized = true;
7543
- if (this.variable instanceof LocalVariable) {
7544
- this.variable.consolidateInitializers();
7545
- this.scope.context.requestTreeshakingPass();
7546
- }
7547
- if (this.isReferenceVariable) {
7548
- this.variable.addUsedPlace(this);
7549
- }
7594
+ addReturnExpression(expression) {
7595
+ this.returnExpressions.push(expression);
7550
7596
  }
7551
- getVariableRespectingTDZ() {
7552
- if (this.isPossibleTDZ()) {
7553
- return UNKNOWN_EXPRESSION;
7554
- }
7555
- return this.variable;
7597
+ getReturnExpression() {
7598
+ if (this.returnExpression === null)
7599
+ this.updateReturnExpression();
7600
+ return this.returnExpression;
7556
7601
  }
7557
- isPureFunction(path) {
7558
- let currentPureFunction = this.scope.context.manualPureFunctions[this.name];
7559
- for (const segment of path) {
7560
- if (currentPureFunction) {
7561
- if (currentPureFunction[PureFunctionKey]) {
7562
- return true;
7563
- }
7564
- currentPureFunction = currentPureFunction[segment];
7565
- }
7566
- else {
7567
- return false;
7602
+ updateReturnExpression() {
7603
+ if (this.returnExpressions.length === 1) {
7604
+ this.returnExpression = this.returnExpressions[0];
7605
+ }
7606
+ else {
7607
+ this.returnExpression = UNKNOWN_EXPRESSION;
7608
+ for (const expression of this.returnExpressions) {
7609
+ expression.deoptimizePath(UNKNOWN_PATH);
7568
7610
  }
7569
7611
  }
7570
- return currentPureFunction?.[PureFunctionKey];
7571
- }
7572
- }
7573
- function closestParentFunctionOrProgram(node) {
7574
- while (node && !/^Program|Function/.test(node.type)) {
7575
- node = node.parent;
7576
7612
  }
7577
- // one of: ArrowFunctionExpression, FunctionDeclaration, FunctionExpression or Program
7578
- return node;
7579
7613
  }
7580
7614
 
7581
7615
  function treeshakeNode(node, code, start, end) {
@@ -7866,17 +7900,11 @@ class RestElement extends NodeBase {
7866
7900
  }
7867
7901
  }
7868
7902
 
7869
- // This handler does nothing.
7870
- // Since we always re-evaluate argument values in a new tree-shaking pass,
7871
- // we don't need to get notified if it is deoptimized.
7872
- const EMPTY_DEOPTIMIZABLE_HANDLER = { deoptimizeCache() { } };
7873
7903
  class FunctionBase extends NodeBase {
7874
7904
  constructor() {
7875
7905
  super(...arguments);
7876
- this.knownParameterValues = [];
7877
- this.allArguments = [];
7878
7906
  this.objectEntity = null;
7879
- this.functionParametersOptimized = false;
7907
+ this.parameterVariableValuesDeoptimized = false;
7880
7908
  }
7881
7909
  get async() {
7882
7910
  return isFlagSet(this.flags, 256 /* Flag.async */);
@@ -7896,84 +7924,22 @@ class FunctionBase extends NodeBase {
7896
7924
  set generator(value) {
7897
7925
  this.flags = setFlag(this.flags, 4194304 /* Flag.generator */, value);
7898
7926
  }
7899
- /**
7900
- * update knownParameterValues when a call is made to this function
7901
- * @param newArguments arguments of the call
7902
- */
7903
- updateKnownParameterValues(newArguments) {
7927
+ updateParameterVariableValues(_arguments) {
7904
7928
  for (let position = 0; position < this.params.length; position++) {
7905
- // only the "this" argument newArguments[0] can be null
7906
- // it's possible that some arguments are empty, so the value is undefined
7907
- const argument = newArguments[position + 1] ?? UNDEFINED_EXPRESSION;
7908
7929
  const parameter = this.params[position];
7909
- // RestElement can be, and can only be, the last parameter
7910
- if (parameter instanceof RestElement) {
7911
- return;
7912
- }
7913
- const knownParameterValue = this.knownParameterValues[position];
7914
- if (knownParameterValue === undefined) {
7915
- this.knownParameterValues[position] = argument;
7916
- continue;
7917
- }
7918
- if (knownParameterValue === UNKNOWN_EXPRESSION ||
7919
- knownParameterValue === argument ||
7920
- (knownParameterValue instanceof Identifier &&
7921
- argument instanceof Identifier &&
7922
- knownParameterValue.variable === argument.variable)) {
7930
+ if (!(parameter instanceof Identifier)) {
7923
7931
  continue;
7924
7932
  }
7925
- const oldValue = knownParameterValue.getLiteralValueAtPath(EMPTY_PATH, SHARED_RECURSION_TRACKER, EMPTY_DEOPTIMIZABLE_HANDLER);
7926
- const newValue = argument.getLiteralValueAtPath(EMPTY_PATH, SHARED_RECURSION_TRACKER, EMPTY_DEOPTIMIZABLE_HANDLER);
7927
- if (oldValue !== newValue || typeof oldValue === 'symbol') {
7928
- this.knownParameterValues[position] = UNKNOWN_EXPRESSION;
7929
- } // else both are the same literal, no need to update
7930
- }
7931
- }
7932
- forwardArgumentsForFunctionCalledOnce(newArguments) {
7933
- for (let position = 0; position < this.params.length; position++) {
7934
- const parameter = this.params[position];
7935
- if (parameter instanceof Identifier) {
7936
- const ParameterVariable = parameter.variable;
7937
- const argument = newArguments[position + 1] ?? UNDEFINED_EXPRESSION;
7938
- ParameterVariable?.setKnownValue(argument);
7939
- }
7940
- }
7941
- }
7942
- /**
7943
- * each time tree-shake starts, this method should be called to reoptimize the parameters
7944
- * a parameter's state will change at most twice:
7945
- * `undefined` (no call is made) -> an expression -> `UnknownArgument`
7946
- * we are sure it will converge, and can use state from last iteration
7947
- */
7948
- applyFunctionParameterOptimization() {
7949
- if (this.allArguments.length === 0) {
7950
- return;
7951
- }
7952
- if (this.allArguments.length === 1) {
7953
- // we are sure what knownParameterValues will be, so skip it and do setKnownValue
7954
- this.forwardArgumentsForFunctionCalledOnce(this.allArguments[0]);
7955
- return;
7956
- }
7957
- // reoptimize all arguments, that's why we save them
7958
- for (const argumentsList of this.allArguments) {
7959
- this.updateKnownParameterValues(argumentsList);
7960
- }
7961
- for (let position = 0; position < this.params.length; position++) {
7962
- const parameter = this.params[position];
7963
- // Parameters without default values
7964
- if (parameter instanceof Identifier) {
7965
- const parameterVariable = parameter.variable;
7966
- // Only the RestElement may be undefined
7967
- const knownParameterValue = this.knownParameterValues[position];
7968
- parameterVariable?.setKnownValue(knownParameterValue);
7969
- }
7933
+ const parameterVariable = parameter.variable;
7934
+ const argument = _arguments[position + 1] ?? UNDEFINED_EXPRESSION;
7935
+ parameterVariable.updateKnownValue(argument);
7970
7936
  }
7971
7937
  }
7972
- deoptimizeFunctionParameters() {
7938
+ deoptimizeParameterVariableValues() {
7973
7939
  for (const parameter of this.params) {
7974
7940
  if (parameter instanceof Identifier) {
7975
7941
  const parameterVariable = parameter.variable;
7976
- parameterVariable?.markReassigned();
7942
+ parameterVariable.markReassigned();
7977
7943
  }
7978
7944
  }
7979
7945
  }
@@ -8001,7 +7967,7 @@ class FunctionBase extends NodeBase {
8001
7967
  this.addArgumentToBeDeoptimized(argument);
8002
7968
  }
8003
7969
  }
8004
- this.allArguments.push(args);
7970
+ this.updateParameterVariableValues(args);
8005
7971
  }
8006
7972
  else {
8007
7973
  this.getObjectEntity().deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker);
@@ -8076,14 +8042,10 @@ class FunctionBase extends NodeBase {
8076
8042
  return variable?.getOnlyFunctionCallUsed() ?? false;
8077
8043
  }
8078
8044
  include(context, includeChildrenRecursively) {
8079
- const shouldOptimizeFunctionParameters = this.onlyFunctionCallUsed();
8080
- if (shouldOptimizeFunctionParameters) {
8081
- this.applyFunctionParameterOptimization();
8082
- }
8083
- else if (this.functionParametersOptimized) {
8084
- this.deoptimizeFunctionParameters();
8045
+ if (!this.parameterVariableValuesDeoptimized && !this.onlyFunctionCallUsed()) {
8046
+ this.parameterVariableValuesDeoptimized = true;
8047
+ this.deoptimizeParameterVariableValues();
8085
8048
  }
8086
- this.functionParametersOptimized = shouldOptimizeFunctionParameters;
8087
8049
  if (!this.deoptimized)
8088
8050
  this.applyDeoptimizations();
8089
8051
  this.included = true;
@@ -8838,7 +8800,7 @@ class MemberExpression extends NodeBase {
8838
8800
  }
8839
8801
  deoptimizeCache() {
8840
8802
  const { expressionsToBeDeoptimized, object } = this;
8841
- this.expressionsToBeDeoptimized = [];
8803
+ this.expressionsToBeDeoptimized = EMPTY_ARRAY;
8842
8804
  this.propertyKey = UnknownKey;
8843
8805
  object.deoptimizePath(UNKNOWN_PATH);
8844
8806
  for (const expression of expressionsToBeDeoptimized) {
@@ -8989,6 +8951,7 @@ class MemberExpression extends NodeBase {
8989
8951
  }
8990
8952
  if (this.variable) {
8991
8953
  this.variable.addUsedPlace(this);
8954
+ this.scope.context.requestTreeshakingPass();
8992
8955
  }
8993
8956
  }
8994
8957
  applyAssignmentDeoptimization() {
@@ -9188,21 +9151,17 @@ class CallExpression extends CallExpressionBase {
9188
9151
  };
9189
9152
  }
9190
9153
  hasEffects(context) {
9191
- try {
9192
- for (const argument of this.arguments) {
9193
- if (argument.hasEffects(context))
9194
- return true;
9195
- }
9196
- if (this.annotationPure) {
9197
- return false;
9198
- }
9199
- return (this.callee.hasEffects(context) ||
9200
- this.callee.hasEffectsOnInteractionAtPath(EMPTY_PATH, this.interaction, context));
9154
+ if (!this.deoptimized)
9155
+ this.applyDeoptimizations();
9156
+ for (const argument of this.arguments) {
9157
+ if (argument.hasEffects(context))
9158
+ return true;
9201
9159
  }
9202
- finally {
9203
- if (!this.deoptimized)
9204
- this.applyDeoptimizations();
9160
+ if (this.annotationPure) {
9161
+ return false;
9205
9162
  }
9163
+ return (this.callee.hasEffects(context) ||
9164
+ this.callee.hasEffectsOnInteractionAtPath(EMPTY_PATH, this.interaction, context));
9206
9165
  }
9207
9166
  include(context, includeChildrenRecursively) {
9208
9167
  if (!this.deoptimized)
@@ -9639,24 +9598,15 @@ class ConditionalExpression extends NodeBase {
9639
9598
  this.alternate.deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker);
9640
9599
  }
9641
9600
  deoptimizeCache() {
9642
- if (this.usedBranch ||
9643
- this.isBranchResolutionAnalysed ||
9644
- this.expressionsToBeDeoptimized.length > 0) {
9645
- // Request another pass because we need to ensure "include" runs again if it is rendered
9646
- this.scope.context.requestTreeshakingPass();
9647
- }
9648
- const { expressionsToBeDeoptimized } = this;
9649
- if (expressionsToBeDeoptimized.length > 0) {
9650
- this.expressionsToBeDeoptimized = [];
9651
- for (const expression of expressionsToBeDeoptimized) {
9652
- expression.deoptimizeCache();
9653
- }
9654
- }
9655
- this.isBranchResolutionAnalysed = false;
9656
9601
  if (this.usedBranch !== null) {
9657
9602
  const unusedBranch = this.usedBranch === this.consequent ? this.alternate : this.consequent;
9658
9603
  this.usedBranch = null;
9659
9604
  unusedBranch.deoptimizePath(UNKNOWN_PATH);
9605
+ const { expressionsToBeDeoptimized } = this;
9606
+ this.expressionsToBeDeoptimized = EMPTY_ARRAY;
9607
+ for (const expression of expressionsToBeDeoptimized) {
9608
+ expression.deoptimizeCache();
9609
+ }
9660
9610
  }
9661
9611
  }
9662
9612
  deoptimizePath(path) {
@@ -9670,10 +9620,10 @@ class ConditionalExpression extends NodeBase {
9670
9620
  }
9671
9621
  }
9672
9622
  getLiteralValueAtPath(path, recursionTracker, origin) {
9673
- this.expressionsToBeDeoptimized.push(origin);
9674
9623
  const usedBranch = this.getUsedBranch();
9675
9624
  if (!usedBranch)
9676
9625
  return UnknownValue;
9626
+ this.expressionsToBeDeoptimized.push(origin);
9677
9627
  return usedBranch.getLiteralValueAtPath(path, recursionTracker, origin);
9678
9628
  }
9679
9629
  getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin) {
@@ -10170,7 +10120,7 @@ class IfStatement extends NodeBase {
10170
10120
  this.testValue = unset;
10171
10121
  }
10172
10122
  deoptimizeCache() {
10173
- this.testValue = unset;
10123
+ this.testValue = UnknownValue;
10174
10124
  }
10175
10125
  hasEffects(context) {
10176
10126
  if (this.test.hasEffects(context)) {
@@ -10978,24 +10928,18 @@ class LogicalExpression extends NodeBase {
10978
10928
  this.right.deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker);
10979
10929
  }
10980
10930
  deoptimizeCache() {
10981
- if (this.usedBranch ||
10982
- this.isBranchResolutionAnalysed ||
10983
- this.expressionsToBeDeoptimized.length > 0) {
10984
- // Request another pass because we need to ensure "include" runs again if it is rendered
10985
- this.scope.context.requestTreeshakingPass();
10986
- }
10987
- const { expressionsToBeDeoptimized } = this;
10988
- if (expressionsToBeDeoptimized.length > 0) {
10989
- this.expressionsToBeDeoptimized = [];
10990
- for (const expression of expressionsToBeDeoptimized) {
10991
- expression.deoptimizeCache();
10992
- }
10993
- }
10994
- this.isBranchResolutionAnalysed = false;
10995
10931
  if (this.usedBranch) {
10996
10932
  const unusedBranch = this.usedBranch === this.left ? this.right : this.left;
10997
10933
  this.usedBranch = null;
10998
10934
  unusedBranch.deoptimizePath(UNKNOWN_PATH);
10935
+ const { scope: { context }, expressionsToBeDeoptimized } = this;
10936
+ this.expressionsToBeDeoptimized = EMPTY_ARRAY;
10937
+ for (const expression of expressionsToBeDeoptimized) {
10938
+ expression.deoptimizeCache();
10939
+ }
10940
+ // Request another pass because we need to ensure "include" runs again if
10941
+ // it is rendered
10942
+ context.requestTreeshakingPass();
10999
10943
  }
11000
10944
  }
11001
10945
  deoptimizePath(path) {
@@ -11009,10 +10953,10 @@ class LogicalExpression extends NodeBase {
11009
10953
  }
11010
10954
  }
11011
10955
  getLiteralValueAtPath(path, recursionTracker, origin) {
11012
- this.expressionsToBeDeoptimized.push(origin);
11013
10956
  const usedBranch = this.getUsedBranch();
11014
10957
  if (!usedBranch)
11015
10958
  return UnknownValue;
10959
+ this.expressionsToBeDeoptimized.push(origin);
11016
10960
  return usedBranch.getLiteralValueAtPath(path, recursionTracker, origin);
11017
10961
  }
11018
10962
  getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin) {