@rollup/wasm-node 4.16.4 → 4.17.1
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.
- package/dist/bin/rollup +3 -4
- package/dist/es/getLogFilter.js +2 -2
- package/dist/es/parseAst.js +2 -2
- package/dist/es/rollup.js +2 -2
- package/dist/es/shared/node-entry.js +1113 -949
- package/dist/es/shared/parseAst.js +9 -7
- package/dist/es/shared/watch.js +2 -2
- package/dist/getLogFilter.js +2 -2
- package/dist/loadConfigFile.js +2 -2
- package/dist/parseAst.js +2 -2
- package/dist/rollup.js +2 -2
- package/dist/shared/fsevents-importer.js +2 -2
- package/dist/shared/index.js +2 -2
- package/dist/shared/loadConfigFile.js +2 -2
- package/dist/shared/parseAst.js +10 -6
- package/dist/shared/rollup.js +1098 -934
- package/dist/shared/watch-cli.js +2 -2
- package/dist/shared/watch.js +2 -2
- package/dist/wasm-node/bindings_wasm_bg.wasm +0 -0
- package/package.json +14 -13
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/*
|
|
2
2
|
@license
|
|
3
|
-
Rollup.js v4.
|
|
4
|
-
|
|
3
|
+
Rollup.js v4.17.1
|
|
4
|
+
Mon, 29 Apr 2024 04:57:19 GMT - commit dbf0a2e5d3c3eae09ac4d502646d0ecab63f40fd
|
|
5
5
|
|
|
6
6
|
https://github.com/rollup/rollup
|
|
7
7
|
|
|
8
8
|
Released under the MIT License.
|
|
9
9
|
*/
|
|
10
|
-
import { normalize, getImportPath, EMPTY_ARRAY, LOGLEVEL_WARN, logUnusedExternalImports, ANNOTATION_KEY, INVALID_ANNOTATION_KEY, Program as Program$1, logRedeclarationError, CatchClause as CatchClause$1, logDuplicateArgumentNameError,
|
|
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.
|
|
19
|
+
var version = "4.17.1";
|
|
20
20
|
|
|
21
21
|
const comma = ','.charCodeAt(0);
|
|
22
22
|
const semicolon = ';'.charCodeAt(0);
|
|
@@ -1937,6 +1937,9 @@ const NODE_INTERACTION_UNKNOWN_CALL = {
|
|
|
1937
1937
|
};
|
|
1938
1938
|
|
|
1939
1939
|
class Variable extends ExpressionEntity {
|
|
1940
|
+
markReassigned() {
|
|
1941
|
+
this.isReassigned = true;
|
|
1942
|
+
}
|
|
1940
1943
|
constructor(name) {
|
|
1941
1944
|
super();
|
|
1942
1945
|
this.name = name;
|
|
@@ -1944,16 +1947,35 @@ class Variable extends ExpressionEntity {
|
|
|
1944
1947
|
this.forbiddenNames = null;
|
|
1945
1948
|
this.initReached = false;
|
|
1946
1949
|
this.isId = false;
|
|
1947
|
-
this.isReassigned = false;
|
|
1948
1950
|
this.kind = null;
|
|
1949
1951
|
this.renderBaseName = null;
|
|
1950
1952
|
this.renderName = null;
|
|
1953
|
+
this.isReassigned = false;
|
|
1954
|
+
this.onlyFunctionCallUsed = true;
|
|
1951
1955
|
}
|
|
1952
1956
|
/**
|
|
1953
1957
|
* Binds identifiers that reference this variable to this variable.
|
|
1954
1958
|
* Necessary to be able to change variable names.
|
|
1955
1959
|
*/
|
|
1956
1960
|
addReference(_identifier) { }
|
|
1961
|
+
/**
|
|
1962
|
+
* Check if the identifier variable is only used as function call
|
|
1963
|
+
* @returns true if the variable is only used as function call
|
|
1964
|
+
*/
|
|
1965
|
+
getOnlyFunctionCallUsed() {
|
|
1966
|
+
return this.onlyFunctionCallUsed;
|
|
1967
|
+
}
|
|
1968
|
+
/**
|
|
1969
|
+
* Collect the places where the identifier variable is used
|
|
1970
|
+
* @param usedPlace Where the variable is used
|
|
1971
|
+
*/
|
|
1972
|
+
addUsedPlace(usedPlace) {
|
|
1973
|
+
const isFunctionCall = usedPlace.parent.type === CallExpression$1 &&
|
|
1974
|
+
usedPlace.parent.callee === usedPlace;
|
|
1975
|
+
if (!isFunctionCall && usedPlace.parent.type !== ExportDefaultDeclaration$1) {
|
|
1976
|
+
this.onlyFunctionCallUsed = false;
|
|
1977
|
+
}
|
|
1978
|
+
}
|
|
1957
1979
|
/**
|
|
1958
1980
|
* Prevent this variable from being renamed to this name to avoid name
|
|
1959
1981
|
* collisions
|
|
@@ -5654,692 +5676,129 @@ class ArrayPattern extends NodeBase {
|
|
|
5654
5676
|
}
|
|
5655
5677
|
}
|
|
5656
5678
|
|
|
5657
|
-
|
|
5658
|
-
|
|
5659
|
-
|
|
5660
|
-
|
|
5661
|
-
|
|
5662
|
-
|
|
5663
|
-
|
|
5664
|
-
|
|
5665
|
-
|
|
5666
|
-
|
|
5667
|
-
|
|
5668
|
-
|
|
5669
|
-
|
|
5670
|
-
|
|
5671
|
-
|
|
5672
|
-
|
|
5673
|
-
|
|
5674
|
-
|
|
5675
|
-
|
|
5676
|
-
|
|
5677
|
-
|
|
5678
|
-
|
|
5679
|
-
|
|
5680
|
-
|
|
5681
|
-
|
|
5682
|
-
|
|
5683
|
-
|
|
5684
|
-
|
|
5685
|
-
|
|
5686
|
-
|
|
5687
|
-
|
|
5688
|
-
|
|
5689
|
-
|
|
5690
|
-
|
|
5691
|
-
|
|
5692
|
-
|
|
5693
|
-
|
|
5694
|
-
|
|
5695
|
-
|
|
5696
|
-
|
|
5697
|
-
|
|
5698
|
-
|
|
5699
|
-
|
|
5700
|
-
|
|
5701
|
-
|
|
5702
|
-
|
|
5703
|
-
|
|
5704
|
-
|
|
5705
|
-
|
|
5706
|
-
|
|
5707
|
-
|
|
5708
|
-
|
|
5709
|
-
|
|
5710
|
-
|
|
5711
|
-
|
|
5712
|
-
|
|
5713
|
-
|
|
5714
|
-
}
|
|
5715
|
-
getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin) {
|
|
5716
|
-
if (this.isReassigned) {
|
|
5717
|
-
return UNKNOWN_RETURN_EXPRESSION;
|
|
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);
|
|
5718
5736
|
}
|
|
5719
|
-
|
|
5720
|
-
this.expressionsToBeDeoptimized.push(origin);
|
|
5721
|
-
return this.init.getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin);
|
|
5722
|
-
}, UNKNOWN_RETURN_EXPRESSION);
|
|
5737
|
+
currentFunctions[PureFunctionKey] = true;
|
|
5723
5738
|
}
|
|
5724
|
-
|
|
5725
|
-
|
|
5726
|
-
|
|
5727
|
-
|
|
5728
|
-
|
|
5729
|
-
|
|
5730
|
-
|
|
5731
|
-
|
|
5732
|
-
|
|
5733
|
-
|
|
5734
|
-
|
|
5735
|
-
|
|
5736
|
-
|
|
5737
|
-
|
|
5738
|
-
|
|
5739
|
-
|
|
5740
|
-
|
|
5741
|
-
|
|
5742
|
-
|
|
5743
|
-
|
|
5744
|
-
|
|
5745
|
-
|
|
5746
|
-
|
|
5747
|
-
|
|
5748
|
-
|
|
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);
|
|
5749
5764
|
}
|
|
5750
|
-
|
|
5751
|
-
|
|
5752
|
-
|
|
5753
|
-
|
|
5754
|
-
|
|
5755
|
-
|
|
5756
|
-
|
|
5757
|
-
|
|
5758
|
-
while (!node.included) {
|
|
5759
|
-
// We do not want to properly include parents in case they are part of a dead branch
|
|
5760
|
-
// in which case .include() might pull in more dead code
|
|
5761
|
-
node.included = true;
|
|
5762
|
-
if (node.type === Program$1)
|
|
5763
|
-
break;
|
|
5764
|
-
node = node.parent;
|
|
5765
|
-
}
|
|
5766
|
-
}
|
|
5767
|
-
}
|
|
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));
|
|
5768
5773
|
}
|
|
5769
|
-
|
|
5770
|
-
|
|
5771
|
-
|
|
5772
|
-
|
|
5773
|
-
|
|
5774
|
-
|
|
5775
|
-
|
|
5776
|
-
|
|
5777
|
-
|
|
5778
|
-
|
|
5779
|
-
|
|
5780
|
-
|
|
5781
|
-
|
|
5782
|
-
|
|
5783
|
-
|
|
5784
|
-
|
|
5785
|
-
|
|
5786
|
-
|
|
5787
|
-
|
|
5788
|
-
|
|
5789
|
-
|
|
5790
|
-
|
|
5791
|
-
|
|
5792
|
-
}
|
|
5793
|
-
|
|
5794
|
-
|
|
5795
|
-
|
|
5796
|
-
|
|
5797
|
-
const EMPTY_PATH_TRACKER = new PathTracker();
|
|
5798
|
-
const UNKNOWN_DEOPTIMIZED_ENTITY = new Set([UNKNOWN_EXPRESSION]);
|
|
5799
|
-
class ParameterVariable extends LocalVariable {
|
|
5800
|
-
constructor(name, declarator, context) {
|
|
5801
|
-
super(name, declarator, UNKNOWN_EXPRESSION, context, 'parameter');
|
|
5802
|
-
this.deoptimizationInteractions = [];
|
|
5803
|
-
this.deoptimizations = new PathTracker();
|
|
5804
|
-
this.deoptimizedFields = new Set();
|
|
5805
|
-
this.entitiesToBeDeoptimized = new Set();
|
|
5806
|
-
}
|
|
5807
|
-
addEntityToBeDeoptimized(entity) {
|
|
5808
|
-
if (entity === UNKNOWN_EXPRESSION) {
|
|
5809
|
-
// As unknown expressions fully deoptimize all interactions, we can clear
|
|
5810
|
-
// the interaction cache at this point provided we keep this optimization
|
|
5811
|
-
// in mind when adding new interactions
|
|
5812
|
-
if (!this.entitiesToBeDeoptimized.has(UNKNOWN_EXPRESSION)) {
|
|
5813
|
-
this.entitiesToBeDeoptimized.add(UNKNOWN_EXPRESSION);
|
|
5814
|
-
for (const { interaction } of this.deoptimizationInteractions) {
|
|
5815
|
-
deoptimizeInteraction(interaction);
|
|
5816
|
-
}
|
|
5817
|
-
this.deoptimizationInteractions = NO_INTERACTIONS;
|
|
5818
|
-
}
|
|
5819
|
-
}
|
|
5820
|
-
else if (this.deoptimizedFields.has(UnknownKey)) {
|
|
5821
|
-
// This means that we already deoptimized all interactions and no longer
|
|
5822
|
-
// track them
|
|
5823
|
-
entity.deoptimizePath(UNKNOWN_PATH);
|
|
5824
|
-
}
|
|
5825
|
-
else if (!this.entitiesToBeDeoptimized.has(entity)) {
|
|
5826
|
-
this.entitiesToBeDeoptimized.add(entity);
|
|
5827
|
-
for (const field of this.deoptimizedFields) {
|
|
5828
|
-
entity.deoptimizePath([field]);
|
|
5829
|
-
}
|
|
5830
|
-
for (const { interaction, path } of this.deoptimizationInteractions) {
|
|
5831
|
-
entity.deoptimizeArgumentsOnInteractionAtPath(interaction, path, SHARED_RECURSION_TRACKER);
|
|
5832
|
-
}
|
|
5833
|
-
}
|
|
5834
|
-
}
|
|
5835
|
-
deoptimizeArgumentsOnInteractionAtPath(interaction, path) {
|
|
5836
|
-
// For performance reasons, we fully deoptimize all deeper interactions
|
|
5837
|
-
if (path.length >= 2 ||
|
|
5838
|
-
this.entitiesToBeDeoptimized.has(UNKNOWN_EXPRESSION) ||
|
|
5839
|
-
this.deoptimizationInteractions.length >= MAX_TRACKED_INTERACTIONS ||
|
|
5840
|
-
(path.length === 1 &&
|
|
5841
|
-
(this.deoptimizedFields.has(UnknownKey) ||
|
|
5842
|
-
(interaction.type === INTERACTION_CALLED && this.deoptimizedFields.has(path[0]))))) {
|
|
5843
|
-
deoptimizeInteraction(interaction);
|
|
5844
|
-
return;
|
|
5845
|
-
}
|
|
5846
|
-
if (!this.deoptimizations.trackEntityAtPathAndGetIfTracked(path, interaction.args)) {
|
|
5847
|
-
for (const entity of this.entitiesToBeDeoptimized) {
|
|
5848
|
-
entity.deoptimizeArgumentsOnInteractionAtPath(interaction, path, SHARED_RECURSION_TRACKER);
|
|
5849
|
-
}
|
|
5850
|
-
if (!this.entitiesToBeDeoptimized.has(UNKNOWN_EXPRESSION)) {
|
|
5851
|
-
this.deoptimizationInteractions.push({
|
|
5852
|
-
interaction,
|
|
5853
|
-
path
|
|
5854
|
-
});
|
|
5855
|
-
}
|
|
5856
|
-
}
|
|
5857
|
-
}
|
|
5858
|
-
deoptimizePath(path) {
|
|
5859
|
-
if (path.length === 0 || this.deoptimizedFields.has(UnknownKey)) {
|
|
5860
|
-
return;
|
|
5861
|
-
}
|
|
5862
|
-
const key = path[0];
|
|
5863
|
-
if (this.deoptimizedFields.has(key)) {
|
|
5864
|
-
return;
|
|
5865
|
-
}
|
|
5866
|
-
this.deoptimizedFields.add(key);
|
|
5867
|
-
for (const entity of this.entitiesToBeDeoptimized) {
|
|
5868
|
-
// We do not need a recursion tracker here as we already track whether
|
|
5869
|
-
// this field is deoptimized
|
|
5870
|
-
entity.deoptimizePath([key]);
|
|
5871
|
-
}
|
|
5872
|
-
if (key === UnknownKey) {
|
|
5873
|
-
// save some memory
|
|
5874
|
-
this.deoptimizationInteractions = NO_INTERACTIONS;
|
|
5875
|
-
this.deoptimizations = EMPTY_PATH_TRACKER;
|
|
5876
|
-
this.deoptimizedFields = UNKNOWN_DEOPTIMIZED_FIELD;
|
|
5877
|
-
this.entitiesToBeDeoptimized = UNKNOWN_DEOPTIMIZED_ENTITY;
|
|
5878
|
-
}
|
|
5879
|
-
}
|
|
5880
|
-
getReturnExpressionWhenCalledAtPath(path) {
|
|
5881
|
-
// We deoptimize everything that is called as that will trivially deoptimize
|
|
5882
|
-
// the corresponding return expressions as well and avoid badly performing
|
|
5883
|
-
// and complicated alternatives
|
|
5884
|
-
if (path.length === 0) {
|
|
5885
|
-
this.deoptimizePath(UNKNOWN_PATH);
|
|
5886
|
-
}
|
|
5887
|
-
else if (!this.deoptimizedFields.has(path[0])) {
|
|
5888
|
-
this.deoptimizePath([path[0]]);
|
|
5889
|
-
}
|
|
5890
|
-
return UNKNOWN_RETURN_EXPRESSION;
|
|
5891
|
-
}
|
|
5892
|
-
}
|
|
5893
|
-
|
|
5894
|
-
const chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_$';
|
|
5895
|
-
const base = 64;
|
|
5896
|
-
function toBase64(value) {
|
|
5897
|
-
let outString = '';
|
|
5898
|
-
do {
|
|
5899
|
-
const currentDigit = value % base;
|
|
5900
|
-
value = (value / base) | 0;
|
|
5901
|
-
outString = chars[currentDigit] + outString;
|
|
5902
|
-
} while (value !== 0);
|
|
5903
|
-
return outString;
|
|
5904
|
-
}
|
|
5905
|
-
|
|
5906
|
-
function getSafeName(baseName, usedNames, forbiddenNames) {
|
|
5907
|
-
let safeName = baseName;
|
|
5908
|
-
let count = 1;
|
|
5909
|
-
while (usedNames.has(safeName) || RESERVED_NAMES.has(safeName) || forbiddenNames?.has(safeName)) {
|
|
5910
|
-
safeName = `${baseName}$${toBase64(count++)}`;
|
|
5911
|
-
}
|
|
5912
|
-
usedNames.add(safeName);
|
|
5913
|
-
return safeName;
|
|
5914
|
-
}
|
|
5915
|
-
|
|
5916
|
-
class Scope {
|
|
5917
|
-
constructor() {
|
|
5918
|
-
this.children = [];
|
|
5919
|
-
this.variables = new Map();
|
|
5920
|
-
}
|
|
5921
|
-
/*
|
|
5922
|
-
Redeclaration rules:
|
|
5923
|
-
- var can redeclare var
|
|
5924
|
-
- in function scopes, function and var can redeclare function and var
|
|
5925
|
-
- var is hoisted across scopes, function remains in the scope it is declared
|
|
5926
|
-
- var and function can redeclare function parameters, but parameters cannot redeclare parameters
|
|
5927
|
-
- function cannot redeclare catch scope parameters
|
|
5928
|
-
- var can redeclare catch scope parameters in a way
|
|
5929
|
-
- if the parameter is an identifier and not a pattern
|
|
5930
|
-
- then the variable is still declared in the hoisted outer scope, but the initializer is assigned to the parameter
|
|
5931
|
-
- const, let, class, and function except in the cases above cannot redeclare anything
|
|
5932
|
-
*/
|
|
5933
|
-
addDeclaration(identifier, context, init, kind) {
|
|
5934
|
-
const name = identifier.name;
|
|
5935
|
-
const existingVariable = this.hoistedVariables?.get(name) || this.variables.get(name);
|
|
5936
|
-
if (existingVariable) {
|
|
5937
|
-
const existingKind = existingVariable.kind;
|
|
5938
|
-
if (kind === 'var' && existingKind === 'var') {
|
|
5939
|
-
existingVariable.addDeclaration(identifier, init);
|
|
5940
|
-
return existingVariable;
|
|
5941
|
-
}
|
|
5942
|
-
context.error(logRedeclarationError(name), identifier.start);
|
|
5943
|
-
}
|
|
5944
|
-
const newVariable = new LocalVariable(identifier.name, identifier, init, context, kind);
|
|
5945
|
-
this.variables.set(name, newVariable);
|
|
5946
|
-
return newVariable;
|
|
5947
|
-
}
|
|
5948
|
-
addHoistedVariable(name, variable) {
|
|
5949
|
-
(this.hoistedVariables ||= new Map()).set(name, variable);
|
|
5950
|
-
}
|
|
5951
|
-
contains(name) {
|
|
5952
|
-
return this.variables.has(name);
|
|
5953
|
-
}
|
|
5954
|
-
findVariable(_name) {
|
|
5955
|
-
/* istanbul ignore next */
|
|
5956
|
-
throw new Error('Internal Error: findVariable needs to be implemented by a subclass');
|
|
5957
|
-
}
|
|
5958
|
-
}
|
|
5959
|
-
|
|
5960
|
-
class ChildScope extends Scope {
|
|
5961
|
-
constructor(parent, context) {
|
|
5962
|
-
super();
|
|
5963
|
-
this.parent = parent;
|
|
5964
|
-
this.context = context;
|
|
5965
|
-
this.accessedOutsideVariables = new Map();
|
|
5966
|
-
parent.children.push(this);
|
|
5967
|
-
}
|
|
5968
|
-
addAccessedDynamicImport(importExpression) {
|
|
5969
|
-
(this.accessedDynamicImports || (this.accessedDynamicImports = new Set())).add(importExpression);
|
|
5970
|
-
if (this.parent instanceof ChildScope) {
|
|
5971
|
-
this.parent.addAccessedDynamicImport(importExpression);
|
|
5972
|
-
}
|
|
5973
|
-
}
|
|
5974
|
-
addAccessedGlobals(globals, accessedGlobalsByScope) {
|
|
5975
|
-
const accessedGlobals = accessedGlobalsByScope.get(this) || new Set();
|
|
5976
|
-
for (const name of globals) {
|
|
5977
|
-
accessedGlobals.add(name);
|
|
5978
|
-
}
|
|
5979
|
-
accessedGlobalsByScope.set(this, accessedGlobals);
|
|
5980
|
-
if (this.parent instanceof ChildScope) {
|
|
5981
|
-
this.parent.addAccessedGlobals(globals, accessedGlobalsByScope);
|
|
5982
|
-
}
|
|
5983
|
-
}
|
|
5984
|
-
addNamespaceMemberAccess(name, variable) {
|
|
5985
|
-
this.accessedOutsideVariables.set(name, variable);
|
|
5986
|
-
this.parent.addNamespaceMemberAccess(name, variable);
|
|
5987
|
-
}
|
|
5988
|
-
addReturnExpression(expression) {
|
|
5989
|
-
this.parent instanceof ChildScope && this.parent.addReturnExpression(expression);
|
|
5990
|
-
}
|
|
5991
|
-
addUsedOutsideNames(usedNames, format, exportNamesByVariable, accessedGlobalsByScope) {
|
|
5992
|
-
for (const variable of this.accessedOutsideVariables.values()) {
|
|
5993
|
-
if (variable.included) {
|
|
5994
|
-
usedNames.add(variable.getBaseVariableName());
|
|
5995
|
-
if (format === 'system' && exportNamesByVariable.has(variable)) {
|
|
5996
|
-
usedNames.add('exports');
|
|
5997
|
-
}
|
|
5998
|
-
}
|
|
5999
|
-
}
|
|
6000
|
-
const accessedGlobals = accessedGlobalsByScope.get(this);
|
|
6001
|
-
if (accessedGlobals) {
|
|
6002
|
-
for (const name of accessedGlobals) {
|
|
6003
|
-
usedNames.add(name);
|
|
6004
|
-
}
|
|
6005
|
-
}
|
|
6006
|
-
}
|
|
6007
|
-
contains(name) {
|
|
6008
|
-
return this.variables.has(name) || this.parent.contains(name);
|
|
6009
|
-
}
|
|
6010
|
-
deconflict(format, exportNamesByVariable, accessedGlobalsByScope) {
|
|
6011
|
-
const usedNames = new Set();
|
|
6012
|
-
this.addUsedOutsideNames(usedNames, format, exportNamesByVariable, accessedGlobalsByScope);
|
|
6013
|
-
if (this.accessedDynamicImports) {
|
|
6014
|
-
for (const importExpression of this.accessedDynamicImports) {
|
|
6015
|
-
if (importExpression.inlineNamespace) {
|
|
6016
|
-
usedNames.add(importExpression.inlineNamespace.getBaseVariableName());
|
|
6017
|
-
}
|
|
6018
|
-
}
|
|
6019
|
-
}
|
|
6020
|
-
for (const [name, variable] of this.variables) {
|
|
6021
|
-
if (variable.included || variable.alwaysRendered) {
|
|
6022
|
-
variable.setRenderNames(null, getSafeName(name, usedNames, variable.forbiddenNames));
|
|
6023
|
-
}
|
|
6024
|
-
}
|
|
6025
|
-
for (const scope of this.children) {
|
|
6026
|
-
scope.deconflict(format, exportNamesByVariable, accessedGlobalsByScope);
|
|
6027
|
-
}
|
|
6028
|
-
}
|
|
6029
|
-
findLexicalBoundary() {
|
|
6030
|
-
return this.parent.findLexicalBoundary();
|
|
6031
|
-
}
|
|
6032
|
-
findVariable(name) {
|
|
6033
|
-
const knownVariable = this.variables.get(name) || this.accessedOutsideVariables.get(name);
|
|
6034
|
-
if (knownVariable) {
|
|
6035
|
-
return knownVariable;
|
|
6036
|
-
}
|
|
6037
|
-
const variable = this.parent.findVariable(name);
|
|
6038
|
-
this.accessedOutsideVariables.set(name, variable);
|
|
6039
|
-
return variable;
|
|
6040
|
-
}
|
|
6041
|
-
}
|
|
6042
|
-
|
|
6043
|
-
class CatchBodyScope extends ChildScope {
|
|
6044
|
-
constructor(parent) {
|
|
6045
|
-
super(parent, parent.context);
|
|
6046
|
-
this.parent = parent;
|
|
6047
|
-
}
|
|
6048
|
-
addDeclaration(identifier, context, init, kind) {
|
|
6049
|
-
if (kind === 'var') {
|
|
6050
|
-
const name = identifier.name;
|
|
6051
|
-
const existingVariable = this.hoistedVariables?.get(name) || this.variables.get(name);
|
|
6052
|
-
if (existingVariable) {
|
|
6053
|
-
const existingKind = existingVariable.kind;
|
|
6054
|
-
if (existingKind === 'parameter' &&
|
|
6055
|
-
// If this is a destructured parameter, it is forbidden to redeclare
|
|
6056
|
-
existingVariable.declarations[0].parent.type === CatchClause$1) {
|
|
6057
|
-
// If this is a var with the same name as the catch scope parameter,
|
|
6058
|
-
// the assignment actually goes to the parameter and the var is
|
|
6059
|
-
// hoisted without assignment. Locally, it is shadowed by the
|
|
6060
|
-
// parameter
|
|
6061
|
-
const declaredVariable = this.parent.parent.addDeclaration(identifier, context, UNDEFINED_EXPRESSION, kind);
|
|
6062
|
-
// To avoid the need to rewrite the declaration, we link the variable
|
|
6063
|
-
// names. If we ever implement a logic that splits initialization and
|
|
6064
|
-
// assignment for hoisted vars, the "renderLikeHoisted" logic can be
|
|
6065
|
-
// removed again.
|
|
6066
|
-
// We do not need to check whether there already is a linked
|
|
6067
|
-
// variable because then declaredVariable would be that linked
|
|
6068
|
-
// variable.
|
|
6069
|
-
existingVariable.renderLikeHoisted(declaredVariable);
|
|
6070
|
-
this.addHoistedVariable(name, declaredVariable);
|
|
6071
|
-
return declaredVariable;
|
|
6072
|
-
}
|
|
6073
|
-
if (existingKind === 'var') {
|
|
6074
|
-
existingVariable.addDeclaration(identifier, init);
|
|
6075
|
-
return existingVariable;
|
|
6076
|
-
}
|
|
6077
|
-
return context.error(logRedeclarationError(name), identifier.start);
|
|
6078
|
-
}
|
|
6079
|
-
// We only add parameters to parameter scopes
|
|
6080
|
-
const declaredVariable = this.parent.parent.addDeclaration(identifier, context, init, kind);
|
|
6081
|
-
// Necessary to make sure the init is deoptimized for conditional declarations.
|
|
6082
|
-
// We cannot call deoptimizePath here.
|
|
6083
|
-
declaredVariable.markInitializersForDeoptimization();
|
|
6084
|
-
// We add the variable to this and all parent scopes to reliably detect conflicts
|
|
6085
|
-
this.addHoistedVariable(name, declaredVariable);
|
|
6086
|
-
return declaredVariable;
|
|
6087
|
-
}
|
|
6088
|
-
return super.addDeclaration(identifier, context, init, kind);
|
|
6089
|
-
}
|
|
6090
|
-
}
|
|
6091
|
-
|
|
6092
|
-
class FunctionBodyScope extends ChildScope {
|
|
6093
|
-
constructor(parent) {
|
|
6094
|
-
super(parent, parent.context);
|
|
6095
|
-
}
|
|
6096
|
-
// There is stuff that is only allowed in function scopes, i.e. functions can
|
|
6097
|
-
// be redeclared, functions and var can redeclare each other
|
|
6098
|
-
addDeclaration(identifier, context, init, kind) {
|
|
6099
|
-
const name = identifier.name;
|
|
6100
|
-
const existingVariable = this.hoistedVariables?.get(name) || this.variables.get(name);
|
|
6101
|
-
if (existingVariable) {
|
|
6102
|
-
const existingKind = existingVariable.kind;
|
|
6103
|
-
if ((kind === 'var' || kind === 'function') &&
|
|
6104
|
-
(existingKind === 'var' || existingKind === 'function' || existingKind === 'parameter')) {
|
|
6105
|
-
existingVariable.addDeclaration(identifier, init);
|
|
6106
|
-
return existingVariable;
|
|
6107
|
-
}
|
|
6108
|
-
context.error(logRedeclarationError(name), identifier.start);
|
|
6109
|
-
}
|
|
6110
|
-
const newVariable = new LocalVariable(identifier.name, identifier, init, context, kind);
|
|
6111
|
-
this.variables.set(name, newVariable);
|
|
6112
|
-
return newVariable;
|
|
6113
|
-
}
|
|
6114
|
-
}
|
|
6115
|
-
|
|
6116
|
-
class ParameterScope extends ChildScope {
|
|
6117
|
-
constructor(parent, isCatchScope) {
|
|
6118
|
-
super(parent, parent.context);
|
|
6119
|
-
this.parameters = [];
|
|
6120
|
-
this.hasRest = false;
|
|
6121
|
-
this.bodyScope = isCatchScope ? new CatchBodyScope(this) : new FunctionBodyScope(this);
|
|
6122
|
-
}
|
|
6123
|
-
/**
|
|
6124
|
-
* Adds a parameter to this scope. Parameters must be added in the correct
|
|
6125
|
-
* order, i.e. from left to right.
|
|
6126
|
-
*/
|
|
6127
|
-
addParameterDeclaration(identifier) {
|
|
6128
|
-
const { name, start } = identifier;
|
|
6129
|
-
const existingParameter = this.variables.get(name);
|
|
6130
|
-
if (existingParameter) {
|
|
6131
|
-
return this.context.error(logDuplicateArgumentNameError(name), start);
|
|
6132
|
-
}
|
|
6133
|
-
const variable = new ParameterVariable(name, identifier, this.context);
|
|
6134
|
-
this.variables.set(name, variable);
|
|
6135
|
-
// We also add it to the body scope to detect name conflicts with local
|
|
6136
|
-
// variables. We still need the intermediate scope, though, as parameter
|
|
6137
|
-
// defaults are NOT taken from the body scope but from the parameters or
|
|
6138
|
-
// outside scope.
|
|
6139
|
-
this.bodyScope.addHoistedVariable(name, variable);
|
|
6140
|
-
return variable;
|
|
6141
|
-
}
|
|
6142
|
-
addParameterVariables(parameters, hasRest) {
|
|
6143
|
-
this.parameters = parameters;
|
|
6144
|
-
for (const parameterList of parameters) {
|
|
6145
|
-
for (const parameter of parameterList) {
|
|
6146
|
-
parameter.alwaysRendered = true;
|
|
6147
|
-
}
|
|
6148
|
-
}
|
|
6149
|
-
this.hasRest = hasRest;
|
|
6150
|
-
}
|
|
6151
|
-
includeCallArguments(context, parameters) {
|
|
6152
|
-
let calledFromTryStatement = false;
|
|
6153
|
-
let argumentIncluded = false;
|
|
6154
|
-
const restParameter = this.hasRest && this.parameters[this.parameters.length - 1];
|
|
6155
|
-
for (const checkedArgument of parameters) {
|
|
6156
|
-
if (checkedArgument instanceof SpreadElement) {
|
|
6157
|
-
for (const argument of parameters) {
|
|
6158
|
-
argument.include(context, false);
|
|
6159
|
-
}
|
|
6160
|
-
break;
|
|
6161
|
-
}
|
|
6162
|
-
}
|
|
6163
|
-
for (let index = parameters.length - 1; index >= 0; index--) {
|
|
6164
|
-
const parameterVariables = this.parameters[index] || restParameter;
|
|
6165
|
-
const argument = parameters[index];
|
|
6166
|
-
if (parameterVariables) {
|
|
6167
|
-
calledFromTryStatement = false;
|
|
6168
|
-
if (parameterVariables.length === 0) {
|
|
6169
|
-
// handle empty destructuring
|
|
6170
|
-
argumentIncluded = true;
|
|
6171
|
-
}
|
|
6172
|
-
else {
|
|
6173
|
-
for (const variable of parameterVariables) {
|
|
6174
|
-
if (variable.included) {
|
|
6175
|
-
argumentIncluded = true;
|
|
6176
|
-
}
|
|
6177
|
-
if (variable.calledFromTryStatement) {
|
|
6178
|
-
calledFromTryStatement = true;
|
|
6179
|
-
}
|
|
6180
|
-
}
|
|
6181
|
-
}
|
|
6182
|
-
}
|
|
6183
|
-
if (!argumentIncluded && argument.shouldBeIncluded(context)) {
|
|
6184
|
-
argumentIncluded = true;
|
|
6185
|
-
}
|
|
6186
|
-
if (argumentIncluded) {
|
|
6187
|
-
argument.include(context, calledFromTryStatement);
|
|
6188
|
-
}
|
|
6189
|
-
}
|
|
6190
|
-
}
|
|
6191
|
-
}
|
|
6192
|
-
|
|
6193
|
-
class ReturnValueScope extends ParameterScope {
|
|
6194
|
-
constructor() {
|
|
6195
|
-
super(...arguments);
|
|
6196
|
-
this.returnExpression = null;
|
|
6197
|
-
this.returnExpressions = [];
|
|
6198
|
-
}
|
|
6199
|
-
addReturnExpression(expression) {
|
|
6200
|
-
this.returnExpressions.push(expression);
|
|
6201
|
-
}
|
|
6202
|
-
getReturnExpression() {
|
|
6203
|
-
if (this.returnExpression === null)
|
|
6204
|
-
this.updateReturnExpression();
|
|
6205
|
-
return this.returnExpression;
|
|
6206
|
-
}
|
|
6207
|
-
updateReturnExpression() {
|
|
6208
|
-
if (this.returnExpressions.length === 1) {
|
|
6209
|
-
this.returnExpression = this.returnExpressions[0];
|
|
6210
|
-
}
|
|
6211
|
-
else {
|
|
6212
|
-
this.returnExpression = UNKNOWN_EXPRESSION;
|
|
6213
|
-
for (const expression of this.returnExpressions) {
|
|
6214
|
-
expression.deoptimizePath(UNKNOWN_PATH);
|
|
6215
|
-
}
|
|
6216
|
-
}
|
|
6217
|
-
}
|
|
6218
|
-
}
|
|
6219
|
-
|
|
6220
|
-
/** @typedef { import('estree').Node} Node */
|
|
6221
|
-
/** @typedef {Node | {
|
|
6222
|
-
* type: 'PropertyDefinition';
|
|
6223
|
-
* computed: boolean;
|
|
6224
|
-
* value: Node
|
|
6225
|
-
* }} NodeWithPropertyDefinition */
|
|
6226
|
-
|
|
6227
|
-
/**
|
|
6228
|
-
*
|
|
6229
|
-
* @param {NodeWithPropertyDefinition} node
|
|
6230
|
-
* @param {NodeWithPropertyDefinition} parent
|
|
6231
|
-
* @returns {boolean}
|
|
6232
|
-
*/
|
|
6233
|
-
function is_reference (node, parent) {
|
|
6234
|
-
if (node.type === 'MemberExpression') {
|
|
6235
|
-
return !node.computed && is_reference(node.object, node);
|
|
6236
|
-
}
|
|
6237
|
-
|
|
6238
|
-
if (node.type === 'Identifier') {
|
|
6239
|
-
if (!parent) return true;
|
|
6240
|
-
|
|
6241
|
-
switch (parent.type) {
|
|
6242
|
-
// disregard `bar` in `foo.bar`
|
|
6243
|
-
case 'MemberExpression': return parent.computed || node === parent.object;
|
|
6244
|
-
|
|
6245
|
-
// disregard the `foo` in `class {foo(){}}` but keep it in `class {[foo](){}}`
|
|
6246
|
-
case 'MethodDefinition': return parent.computed;
|
|
6247
|
-
|
|
6248
|
-
// disregard the `foo` in `class {foo=bar}` but keep it in `class {[foo]=bar}` and `class {bar=foo}`
|
|
6249
|
-
case 'PropertyDefinition': return parent.computed || node === parent.value;
|
|
6250
|
-
|
|
6251
|
-
// disregard the `bar` in `{ bar: foo }`, but keep it in `{ [bar]: foo }`
|
|
6252
|
-
case 'Property': return parent.computed || node === parent.value;
|
|
6253
|
-
|
|
6254
|
-
// disregard the `bar` in `export { foo as bar }` or
|
|
6255
|
-
// the foo in `import { foo as bar }`
|
|
6256
|
-
case 'ExportSpecifier':
|
|
6257
|
-
case 'ImportSpecifier': return node === parent.local;
|
|
6258
|
-
|
|
6259
|
-
// disregard the `foo` in `foo: while (...) { ... break foo; ... continue foo;}`
|
|
6260
|
-
case 'LabeledStatement':
|
|
6261
|
-
case 'BreakStatement':
|
|
6262
|
-
case 'ContinueStatement': return false;
|
|
6263
|
-
default: return true;
|
|
6264
|
-
}
|
|
6265
|
-
}
|
|
6266
|
-
|
|
6267
|
-
return false;
|
|
6268
|
-
}
|
|
6269
|
-
|
|
6270
|
-
const PureFunctionKey = Symbol('PureFunction');
|
|
6271
|
-
const getPureFunctions = ({ treeshake }) => {
|
|
6272
|
-
const pureFunctions = Object.create(null);
|
|
6273
|
-
for (const functionName of treeshake ? treeshake.manualPureFunctions : []) {
|
|
6274
|
-
let currentFunctions = pureFunctions;
|
|
6275
|
-
for (const pathSegment of functionName.split('.')) {
|
|
6276
|
-
currentFunctions = currentFunctions[pathSegment] ||= Object.create(null);
|
|
6277
|
-
}
|
|
6278
|
-
currentFunctions[PureFunctionKey] = true;
|
|
6279
|
-
}
|
|
6280
|
-
return pureFunctions;
|
|
6281
|
-
};
|
|
6282
|
-
|
|
6283
|
-
const doNothing = () => { };
|
|
6284
|
-
|
|
6285
|
-
/* eslint sort-keys: "off" */
|
|
6286
|
-
const ValueProperties = Symbol('Value Properties');
|
|
6287
|
-
const getTruthyLiteralValue = () => UnknownTruthyValue;
|
|
6288
|
-
const returnFalse = () => false;
|
|
6289
|
-
const returnTrue = () => true;
|
|
6290
|
-
const PURE = {
|
|
6291
|
-
deoptimizeArgumentsOnCall: doNothing,
|
|
6292
|
-
getLiteralValue: getTruthyLiteralValue,
|
|
6293
|
-
hasEffectsWhenCalled: returnFalse
|
|
6294
|
-
};
|
|
6295
|
-
const IMPURE = {
|
|
6296
|
-
deoptimizeArgumentsOnCall: doNothing,
|
|
6297
|
-
getLiteralValue: getTruthyLiteralValue,
|
|
6298
|
-
hasEffectsWhenCalled: returnTrue
|
|
6299
|
-
};
|
|
6300
|
-
const PURE_WITH_ARRAY = {
|
|
6301
|
-
deoptimizeArgumentsOnCall: doNothing,
|
|
6302
|
-
getLiteralValue: getTruthyLiteralValue,
|
|
6303
|
-
hasEffectsWhenCalled({ args }) {
|
|
6304
|
-
return args.length > 1 && !(args[1] instanceof ArrayExpression);
|
|
6305
|
-
}
|
|
6306
|
-
};
|
|
6307
|
-
const GETTER_ACCESS = {
|
|
6308
|
-
deoptimizeArgumentsOnCall: doNothing,
|
|
6309
|
-
getLiteralValue: getTruthyLiteralValue,
|
|
6310
|
-
hasEffectsWhenCalled({ args }, context) {
|
|
6311
|
-
const [_thisArgument, firstArgument] = args;
|
|
6312
|
-
return (!(firstArgument instanceof ExpressionEntity) ||
|
|
6313
|
-
firstArgument.hasEffectsOnInteractionAtPath(UNKNOWN_PATH, NODE_INTERACTION_UNKNOWN_ACCESS, context));
|
|
6314
|
-
}
|
|
6315
|
-
};
|
|
6316
|
-
// We use shortened variables to reduce file size here
|
|
6317
|
-
/* OBJECT */
|
|
6318
|
-
const O = {
|
|
6319
|
-
__proto__: null,
|
|
6320
|
-
[ValueProperties]: IMPURE
|
|
6321
|
-
};
|
|
6322
|
-
/* PURE FUNCTION */
|
|
6323
|
-
const PF = {
|
|
6324
|
-
__proto__: null,
|
|
6325
|
-
[ValueProperties]: PURE
|
|
6326
|
-
};
|
|
6327
|
-
/* PURE FUNCTION IF FIRST ARG DOES NOT CONTAIN A GETTER */
|
|
6328
|
-
const PF_NO_GETTER = {
|
|
6329
|
-
__proto__: null,
|
|
6330
|
-
[ValueProperties]: GETTER_ACCESS
|
|
6331
|
-
};
|
|
6332
|
-
/* FUNCTION THAT MUTATES FIRST ARG WITHOUT TRIGGERING ACCESSORS */
|
|
6333
|
-
const MUTATES_ARG_WITHOUT_ACCESSOR = {
|
|
6334
|
-
__proto__: null,
|
|
6335
|
-
[ValueProperties]: {
|
|
6336
|
-
deoptimizeArgumentsOnCall({ args: [, firstArgument] }) {
|
|
6337
|
-
firstArgument?.deoptimizePath(UNKNOWN_PATH);
|
|
6338
|
-
},
|
|
6339
|
-
getLiteralValue: getTruthyLiteralValue,
|
|
6340
|
-
hasEffectsWhenCalled({ args }, context) {
|
|
6341
|
-
return (args.length <= 1 ||
|
|
6342
|
-
args[1].hasEffectsOnInteractionAtPath(UNKNOWN_NON_ACCESSOR_PATH, NODE_INTERACTION_UNKNOWN_ASSIGNMENT, context));
|
|
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));
|
|
6343
5802
|
}
|
|
6344
5803
|
}
|
|
6345
5804
|
};
|
|
@@ -7217,290 +6676,940 @@ const knownGlobals = {
|
|
|
7217
6676
|
for (const global of ['window', 'global', 'self', 'globalThis']) {
|
|
7218
6677
|
knownGlobals[global] = knownGlobals;
|
|
7219
6678
|
}
|
|
7220
|
-
function getGlobalAtPath(path) {
|
|
7221
|
-
let currentGlobal = knownGlobals;
|
|
7222
|
-
for (const pathSegment of path) {
|
|
7223
|
-
if (typeof pathSegment !== 'string') {
|
|
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 */)) {
|
|
7224
6893
|
return null;
|
|
7225
6894
|
}
|
|
7226
|
-
|
|
7227
|
-
|
|
7228
|
-
|
|
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);
|
|
7229
7038
|
}
|
|
7039
|
+
return (this.isTDZAccess = false);
|
|
7230
7040
|
}
|
|
7231
|
-
|
|
7232
|
-
|
|
7233
|
-
|
|
7234
|
-
class GlobalVariable extends Variable {
|
|
7235
|
-
constructor() {
|
|
7236
|
-
super(...arguments);
|
|
7237
|
-
// Ensure we use live-bindings for globals as we do not know if they have
|
|
7238
|
-
// been reassigned
|
|
7239
|
-
this.isReassigned = true;
|
|
7041
|
+
markDeclarationReached() {
|
|
7042
|
+
this.variable.initReached = true;
|
|
7240
7043
|
}
|
|
7241
|
-
|
|
7242
|
-
|
|
7243
|
-
|
|
7244
|
-
|
|
7245
|
-
|
|
7246
|
-
|
|
7247
|
-
|
|
7248
|
-
|
|
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}: `);
|
|
7249
7054
|
}
|
|
7250
|
-
return;
|
|
7251
7055
|
}
|
|
7252
|
-
|
|
7253
|
-
|
|
7254
|
-
|
|
7255
|
-
|
|
7256
|
-
|
|
7257
|
-
|
|
7258
|
-
|
|
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;
|
|
7259
7090
|
}
|
|
7260
|
-
|
|
7091
|
+
currentPureFunction = currentPureFunction[segment];
|
|
7092
|
+
}
|
|
7093
|
+
else {
|
|
7094
|
+
return false;
|
|
7261
7095
|
}
|
|
7262
7096
|
}
|
|
7097
|
+
return currentPureFunction?.[PureFunctionKey];
|
|
7263
7098
|
}
|
|
7264
|
-
|
|
7265
|
-
|
|
7266
|
-
|
|
7099
|
+
}
|
|
7100
|
+
function closestParentFunctionOrProgram(node) {
|
|
7101
|
+
while (node && !/^Program|Function/.test(node.type)) {
|
|
7102
|
+
node = node.parent;
|
|
7267
7103
|
}
|
|
7268
|
-
|
|
7269
|
-
|
|
7270
|
-
|
|
7271
|
-
|
|
7272
|
-
|
|
7273
|
-
|
|
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);
|
|
7274
7134
|
}
|
|
7275
|
-
|
|
7135
|
+
this.deoptimizationInteractions = NO_INTERACTIONS;
|
|
7276
7136
|
}
|
|
7277
|
-
|
|
7278
|
-
|
|
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]);
|
|
7279
7147
|
}
|
|
7280
|
-
|
|
7281
|
-
|
|
7282
|
-
|
|
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);
|
|
7283
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
7284
|
}
|
|
7285
|
+
return UNKNOWN_RETURN_EXPRESSION;
|
|
7285
7286
|
}
|
|
7286
7287
|
}
|
|
7287
7288
|
|
|
7288
|
-
const
|
|
7289
|
-
|
|
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 {
|
|
7290
7312
|
constructor() {
|
|
7291
|
-
|
|
7292
|
-
this.
|
|
7313
|
+
this.children = [];
|
|
7314
|
+
this.variables = new Map();
|
|
7293
7315
|
}
|
|
7294
|
-
|
|
7295
|
-
|
|
7296
|
-
|
|
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);
|
|
7297
7338
|
}
|
|
7298
|
-
|
|
7339
|
+
const newVariable = new LocalVariable(identifier.name, identifier, init, context, kind);
|
|
7340
|
+
this.variables.set(name, newVariable);
|
|
7341
|
+
return newVariable;
|
|
7299
7342
|
}
|
|
7300
|
-
|
|
7301
|
-
this.
|
|
7302
|
-
this.flags = setFlag(this.flags, 8 /* Flag.tdzAccess */, value);
|
|
7343
|
+
addHoistedVariable(name, variable) {
|
|
7344
|
+
(this.hoistedVariables ||= new Map()).set(name, variable);
|
|
7303
7345
|
}
|
|
7304
|
-
|
|
7305
|
-
|
|
7306
|
-
|
|
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);
|
|
7307
7367
|
}
|
|
7308
7368
|
}
|
|
7309
|
-
|
|
7310
|
-
|
|
7311
|
-
|
|
7312
|
-
|
|
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);
|
|
7313
7377
|
}
|
|
7314
7378
|
}
|
|
7315
|
-
|
|
7316
|
-
|
|
7317
|
-
|
|
7318
|
-
|
|
7319
|
-
|
|
7320
|
-
|
|
7321
|
-
|
|
7322
|
-
|
|
7323
|
-
|
|
7379
|
+
addNamespaceMemberAccess(name, variable) {
|
|
7380
|
+
this.accessedOutsideVariables.set(name, variable);
|
|
7381
|
+
this.parent.addNamespaceMemberAccess(name, variable);
|
|
7382
|
+
}
|
|
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');
|
|
7324
7392
|
}
|
|
7325
|
-
break;
|
|
7326
|
-
}
|
|
7327
|
-
case 'function': {
|
|
7328
|
-
// in strict mode, functions are only hoisted within a scope but not across block scopes
|
|
7329
|
-
variable = this.scope.addDeclaration(this, this.scope.context, init, kind);
|
|
7330
|
-
break;
|
|
7331
|
-
}
|
|
7332
|
-
case 'let':
|
|
7333
|
-
case 'const':
|
|
7334
|
-
case 'using':
|
|
7335
|
-
case 'await using':
|
|
7336
|
-
case 'class': {
|
|
7337
|
-
variable = this.scope.addDeclaration(this, this.scope.context, init, kind);
|
|
7338
|
-
break;
|
|
7339
|
-
}
|
|
7340
|
-
case 'parameter': {
|
|
7341
|
-
variable = this.scope.addParameterDeclaration(this);
|
|
7342
|
-
break;
|
|
7343
7393
|
}
|
|
7344
|
-
|
|
7345
|
-
|
|
7346
|
-
|
|
7347
|
-
|
|
7394
|
+
}
|
|
7395
|
+
const accessedGlobals = accessedGlobalsByScope.get(this);
|
|
7396
|
+
if (accessedGlobals) {
|
|
7397
|
+
for (const name of accessedGlobals) {
|
|
7398
|
+
usedNames.add(name);
|
|
7348
7399
|
}
|
|
7349
7400
|
}
|
|
7350
|
-
return [(this.variable = variable)];
|
|
7351
7401
|
}
|
|
7352
|
-
|
|
7353
|
-
this.
|
|
7402
|
+
contains(name) {
|
|
7403
|
+
return this.variables.has(name) || this.parent.contains(name);
|
|
7354
7404
|
}
|
|
7355
|
-
|
|
7356
|
-
|
|
7357
|
-
|
|
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());
|
|
7412
|
+
}
|
|
7413
|
+
}
|
|
7414
|
+
}
|
|
7415
|
+
for (const [name, variable] of this.variables) {
|
|
7416
|
+
if (variable.included || variable.alwaysRendered) {
|
|
7417
|
+
variable.setRenderNames(null, getSafeName(name, usedNames, variable.forbiddenNames));
|
|
7418
|
+
}
|
|
7419
|
+
}
|
|
7420
|
+
for (const scope of this.children) {
|
|
7421
|
+
scope.deconflict(format, exportNamesByVariable, accessedGlobalsByScope);
|
|
7358
7422
|
}
|
|
7359
|
-
// We keep conditional chaining because an unknown Node could have an
|
|
7360
|
-
// Identifier as property that might be deoptimized by default
|
|
7361
|
-
this.variable?.deoptimizePath(path);
|
|
7362
|
-
}
|
|
7363
|
-
getLiteralValueAtPath(path, recursionTracker, origin) {
|
|
7364
|
-
return this.getVariableRespectingTDZ().getLiteralValueAtPath(path, recursionTracker, origin);
|
|
7365
7423
|
}
|
|
7366
|
-
|
|
7367
|
-
|
|
7368
|
-
return [expression, isPure || this.isPureFunction(path)];
|
|
7424
|
+
findLexicalBoundary() {
|
|
7425
|
+
return this.parent.findLexicalBoundary();
|
|
7369
7426
|
}
|
|
7370
|
-
|
|
7371
|
-
|
|
7372
|
-
|
|
7373
|
-
|
|
7374
|
-
return true;
|
|
7427
|
+
findVariable(name) {
|
|
7428
|
+
const knownVariable = this.variables.get(name) || this.accessedOutsideVariables.get(name);
|
|
7429
|
+
if (knownVariable) {
|
|
7430
|
+
return knownVariable;
|
|
7375
7431
|
}
|
|
7376
|
-
|
|
7377
|
-
|
|
7378
|
-
|
|
7379
|
-
!this.isPureFunction(EMPTY_PATH) &&
|
|
7380
|
-
this.variable.hasEffectsOnInteractionAtPath(EMPTY_PATH, NODE_INTERACTION_UNKNOWN_ACCESS, context));
|
|
7432
|
+
const variable = this.parent.findVariable(name);
|
|
7433
|
+
this.accessedOutsideVariables.set(name, variable);
|
|
7434
|
+
return variable;
|
|
7381
7435
|
}
|
|
7382
|
-
|
|
7383
|
-
|
|
7384
|
-
|
|
7385
|
-
|
|
7386
|
-
|
|
7387
|
-
|
|
7388
|
-
|
|
7389
|
-
|
|
7390
|
-
|
|
7391
|
-
|
|
7392
|
-
|
|
7393
|
-
|
|
7394
|
-
|
|
7436
|
+
}
|
|
7437
|
+
|
|
7438
|
+
class CatchBodyScope extends ChildScope {
|
|
7439
|
+
constructor(parent) {
|
|
7440
|
+
super(parent, parent.context);
|
|
7441
|
+
this.parent = parent;
|
|
7442
|
+
}
|
|
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;
|
|
7467
|
+
}
|
|
7468
|
+
if (existingKind === 'var') {
|
|
7469
|
+
existingVariable.addDeclaration(identifier, init);
|
|
7470
|
+
return existingVariable;
|
|
7471
|
+
}
|
|
7472
|
+
return context.error(logRedeclarationError(name), identifier.start);
|
|
7395
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;
|
|
7396
7482
|
}
|
|
7483
|
+
return super.addDeclaration(identifier, context, init, kind);
|
|
7397
7484
|
}
|
|
7398
|
-
|
|
7399
|
-
|
|
7400
|
-
|
|
7401
|
-
|
|
7402
|
-
|
|
7403
|
-
|
|
7404
|
-
|
|
7485
|
+
}
|
|
7486
|
+
|
|
7487
|
+
class FunctionBodyScope extends ChildScope {
|
|
7488
|
+
constructor(parent) {
|
|
7489
|
+
super(parent, parent.context);
|
|
7490
|
+
}
|
|
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;
|
|
7405
7502
|
}
|
|
7503
|
+
context.error(logRedeclarationError(name), identifier.start);
|
|
7406
7504
|
}
|
|
7505
|
+
const newVariable = new LocalVariable(identifier.name, identifier, init, context, kind);
|
|
7506
|
+
this.variables.set(name, newVariable);
|
|
7507
|
+
return newVariable;
|
|
7407
7508
|
}
|
|
7408
|
-
|
|
7409
|
-
|
|
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);
|
|
7410
7517
|
}
|
|
7411
|
-
|
|
7412
|
-
|
|
7413
|
-
|
|
7414
|
-
|
|
7415
|
-
|
|
7416
|
-
|
|
7417
|
-
|
|
7418
|
-
|
|
7419
|
-
|
|
7420
|
-
// otherwise we get many false positives
|
|
7421
|
-
this.variable.module === this.scope.context.module)) {
|
|
7422
|
-
return (this.isTDZAccess = false);
|
|
7423
|
-
}
|
|
7424
|
-
let decl_id;
|
|
7425
|
-
if (this.variable.declarations &&
|
|
7426
|
-
this.variable.declarations.length === 1 &&
|
|
7427
|
-
(decl_id = this.variable.declarations[0]) &&
|
|
7428
|
-
this.start < decl_id.start &&
|
|
7429
|
-
closestParentFunctionOrProgram(this) === closestParentFunctionOrProgram(decl_id)) {
|
|
7430
|
-
// a variable accessed before its declaration
|
|
7431
|
-
// in the same function or at top level of module
|
|
7432
|
-
return (this.isTDZAccess = true);
|
|
7433
|
-
}
|
|
7434
|
-
// We ignore the case where the module is not yet executed because
|
|
7435
|
-
// moduleSideEffects are false.
|
|
7436
|
-
if (!this.variable.initReached && this.scope.context.module.isExecuted) {
|
|
7437
|
-
// Either a const/let TDZ violation or
|
|
7438
|
-
// var use before declaration was encountered.
|
|
7439
|
-
return (this.isTDZAccess = true);
|
|
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);
|
|
7440
7527
|
}
|
|
7441
|
-
|
|
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;
|
|
7442
7536
|
}
|
|
7443
|
-
|
|
7444
|
-
this.
|
|
7537
|
+
addParameterVariables(parameters, hasRest) {
|
|
7538
|
+
this.parameters = parameters;
|
|
7539
|
+
for (const parameterList of parameters) {
|
|
7540
|
+
for (const parameter of parameterList) {
|
|
7541
|
+
parameter.alwaysRendered = true;
|
|
7542
|
+
}
|
|
7543
|
+
}
|
|
7544
|
+
this.hasRest = hasRest;
|
|
7445
7545
|
}
|
|
7446
|
-
|
|
7447
|
-
|
|
7448
|
-
|
|
7449
|
-
|
|
7450
|
-
|
|
7451
|
-
|
|
7452
|
-
|
|
7453
|
-
|
|
7454
|
-
if (isShorthandProperty) {
|
|
7455
|
-
code.prependRight(this.start, `${this.name}: `);
|
|
7546
|
+
includeCallArguments(context, parameters) {
|
|
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);
|
|
7456
7554
|
}
|
|
7555
|
+
break;
|
|
7457
7556
|
}
|
|
7458
|
-
|
|
7459
|
-
|
|
7460
|
-
|
|
7461
|
-
|
|
7462
|
-
|
|
7557
|
+
}
|
|
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
|
+
}
|
|
7576
|
+
}
|
|
7577
|
+
}
|
|
7578
|
+
if (!argumentIncluded && argument.shouldBeIncluded(context)) {
|
|
7579
|
+
argumentIncluded = true;
|
|
7580
|
+
}
|
|
7581
|
+
if (argumentIncluded) {
|
|
7582
|
+
argument.include(context, calledFromTryStatement);
|
|
7463
7583
|
}
|
|
7464
7584
|
}
|
|
7465
7585
|
}
|
|
7466
|
-
|
|
7467
|
-
|
|
7586
|
+
}
|
|
7587
|
+
|
|
7588
|
+
class ReturnValueScope extends ParameterScope {
|
|
7589
|
+
constructor() {
|
|
7590
|
+
super(...arguments);
|
|
7591
|
+
this.returnExpression = null;
|
|
7592
|
+
this.returnExpressions = [];
|
|
7468
7593
|
}
|
|
7469
|
-
|
|
7470
|
-
this.
|
|
7471
|
-
if (this.variable instanceof LocalVariable) {
|
|
7472
|
-
this.variable.consolidateInitializers();
|
|
7473
|
-
this.scope.context.requestTreeshakingPass();
|
|
7474
|
-
}
|
|
7594
|
+
addReturnExpression(expression) {
|
|
7595
|
+
this.returnExpressions.push(expression);
|
|
7475
7596
|
}
|
|
7476
|
-
|
|
7477
|
-
if (this.
|
|
7478
|
-
|
|
7479
|
-
|
|
7480
|
-
return this.variable;
|
|
7597
|
+
getReturnExpression() {
|
|
7598
|
+
if (this.returnExpression === null)
|
|
7599
|
+
this.updateReturnExpression();
|
|
7600
|
+
return this.returnExpression;
|
|
7481
7601
|
}
|
|
7482
|
-
|
|
7483
|
-
|
|
7484
|
-
|
|
7485
|
-
|
|
7486
|
-
|
|
7487
|
-
|
|
7488
|
-
|
|
7489
|
-
|
|
7490
|
-
}
|
|
7491
|
-
else {
|
|
7492
|
-
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);
|
|
7493
7610
|
}
|
|
7494
7611
|
}
|
|
7495
|
-
return currentPureFunction?.[PureFunctionKey];
|
|
7496
|
-
}
|
|
7497
|
-
}
|
|
7498
|
-
function closestParentFunctionOrProgram(node) {
|
|
7499
|
-
while (node && !/^Program|Function/.test(node.type)) {
|
|
7500
|
-
node = node.parent;
|
|
7501
7612
|
}
|
|
7502
|
-
// one of: ArrowFunctionExpression, FunctionDeclaration, FunctionExpression or Program
|
|
7503
|
-
return node;
|
|
7504
7613
|
}
|
|
7505
7614
|
|
|
7506
7615
|
function treeshakeNode(node, code, start, end) {
|
|
@@ -7795,6 +7904,7 @@ class FunctionBase extends NodeBase {
|
|
|
7795
7904
|
constructor() {
|
|
7796
7905
|
super(...arguments);
|
|
7797
7906
|
this.objectEntity = null;
|
|
7907
|
+
this.parameterVariableValuesDeoptimized = false;
|
|
7798
7908
|
}
|
|
7799
7909
|
get async() {
|
|
7800
7910
|
return isFlagSet(this.flags, 256 /* Flag.async */);
|
|
@@ -7814,6 +7924,25 @@ class FunctionBase extends NodeBase {
|
|
|
7814
7924
|
set generator(value) {
|
|
7815
7925
|
this.flags = setFlag(this.flags, 4194304 /* Flag.generator */, value);
|
|
7816
7926
|
}
|
|
7927
|
+
updateParameterVariableValues(_arguments) {
|
|
7928
|
+
for (let position = 0; position < this.params.length; position++) {
|
|
7929
|
+
const parameter = this.params[position];
|
|
7930
|
+
if (!(parameter instanceof Identifier)) {
|
|
7931
|
+
continue;
|
|
7932
|
+
}
|
|
7933
|
+
const parameterVariable = parameter.variable;
|
|
7934
|
+
const argument = _arguments[position + 1] ?? UNDEFINED_EXPRESSION;
|
|
7935
|
+
parameterVariable.updateKnownValue(argument);
|
|
7936
|
+
}
|
|
7937
|
+
}
|
|
7938
|
+
deoptimizeParameterVariableValues() {
|
|
7939
|
+
for (const parameter of this.params) {
|
|
7940
|
+
if (parameter instanceof Identifier) {
|
|
7941
|
+
const parameterVariable = parameter.variable;
|
|
7942
|
+
parameterVariable.markReassigned();
|
|
7943
|
+
}
|
|
7944
|
+
}
|
|
7945
|
+
}
|
|
7817
7946
|
deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
|
|
7818
7947
|
if (interaction.type === INTERACTION_CALLED) {
|
|
7819
7948
|
const { parameters } = this.scope;
|
|
@@ -7838,6 +7967,7 @@ class FunctionBase extends NodeBase {
|
|
|
7838
7967
|
this.addArgumentToBeDeoptimized(argument);
|
|
7839
7968
|
}
|
|
7840
7969
|
}
|
|
7970
|
+
this.updateParameterVariableValues(args);
|
|
7841
7971
|
}
|
|
7842
7972
|
else {
|
|
7843
7973
|
this.getObjectEntity().deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker);
|
|
@@ -7852,6 +7982,7 @@ class FunctionBase extends NodeBase {
|
|
|
7852
7982
|
for (const parameterList of this.scope.parameters) {
|
|
7853
7983
|
for (const parameter of parameterList) {
|
|
7854
7984
|
parameter.deoptimizePath(UNKNOWN_PATH);
|
|
7985
|
+
parameter.markReassigned();
|
|
7855
7986
|
}
|
|
7856
7987
|
}
|
|
7857
7988
|
}
|
|
@@ -7897,7 +8028,24 @@ class FunctionBase extends NodeBase {
|
|
|
7897
8028
|
}
|
|
7898
8029
|
return false;
|
|
7899
8030
|
}
|
|
8031
|
+
/**
|
|
8032
|
+
* If the function (expression or declaration) is only used as function calls
|
|
8033
|
+
*/
|
|
8034
|
+
onlyFunctionCallUsed() {
|
|
8035
|
+
let variable = null;
|
|
8036
|
+
if (this.parent.type === VariableDeclarator$1) {
|
|
8037
|
+
variable = this.parent.id.variable ?? null;
|
|
8038
|
+
}
|
|
8039
|
+
if (this.parent.type === ExportDefaultDeclaration$1) {
|
|
8040
|
+
variable = this.parent.variable;
|
|
8041
|
+
}
|
|
8042
|
+
return variable?.getOnlyFunctionCallUsed() ?? false;
|
|
8043
|
+
}
|
|
7900
8044
|
include(context, includeChildrenRecursively) {
|
|
8045
|
+
if (!this.parameterVariableValuesDeoptimized && !this.onlyFunctionCallUsed()) {
|
|
8046
|
+
this.parameterVariableValuesDeoptimized = true;
|
|
8047
|
+
this.deoptimizeParameterVariableValues();
|
|
8048
|
+
}
|
|
7901
8049
|
if (!this.deoptimized)
|
|
7902
8050
|
this.applyDeoptimizations();
|
|
7903
8051
|
this.included = true;
|
|
@@ -7981,6 +8129,11 @@ class ArrowFunctionExpression extends FunctionBase {
|
|
|
7981
8129
|
}
|
|
7982
8130
|
return false;
|
|
7983
8131
|
}
|
|
8132
|
+
onlyFunctionCallUsed() {
|
|
8133
|
+
const isIIFE = this.parent.type === CallExpression$1 &&
|
|
8134
|
+
this.parent.callee === this;
|
|
8135
|
+
return isIIFE || super.onlyFunctionCallUsed();
|
|
8136
|
+
}
|
|
7984
8137
|
include(context, includeChildrenRecursively) {
|
|
7985
8138
|
super.include(context, includeChildrenRecursively);
|
|
7986
8139
|
for (const parameter of this.params) {
|
|
@@ -8796,6 +8949,10 @@ class MemberExpression extends NodeBase {
|
|
|
8796
8949
|
this.object.deoptimizeArgumentsOnInteractionAtPath(this.accessInteraction, [propertyKey], SHARED_RECURSION_TRACKER);
|
|
8797
8950
|
this.scope.context.requestTreeshakingPass();
|
|
8798
8951
|
}
|
|
8952
|
+
if (this.variable) {
|
|
8953
|
+
this.variable.addUsedPlace(this);
|
|
8954
|
+
this.scope.context.requestTreeshakingPass();
|
|
8955
|
+
}
|
|
8799
8956
|
}
|
|
8800
8957
|
applyAssignmentDeoptimization() {
|
|
8801
8958
|
this.assignmentDeoptimized = true;
|
|
@@ -8994,21 +9151,17 @@ class CallExpression extends CallExpressionBase {
|
|
|
8994
9151
|
};
|
|
8995
9152
|
}
|
|
8996
9153
|
hasEffects(context) {
|
|
8997
|
-
|
|
8998
|
-
|
|
8999
|
-
|
|
9000
|
-
|
|
9001
|
-
|
|
9002
|
-
if (this.annotationPure) {
|
|
9003
|
-
return false;
|
|
9004
|
-
}
|
|
9005
|
-
return (this.callee.hasEffects(context) ||
|
|
9006
|
-
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;
|
|
9007
9159
|
}
|
|
9008
|
-
|
|
9009
|
-
|
|
9010
|
-
this.applyDeoptimizations();
|
|
9160
|
+
if (this.annotationPure) {
|
|
9161
|
+
return false;
|
|
9011
9162
|
}
|
|
9163
|
+
return (this.callee.hasEffects(context) ||
|
|
9164
|
+
this.callee.hasEffectsOnInteractionAtPath(EMPTY_PATH, this.interaction, context));
|
|
9012
9165
|
}
|
|
9013
9166
|
include(context, includeChildrenRecursively) {
|
|
9014
9167
|
if (!this.deoptimized)
|
|
@@ -9669,6 +9822,10 @@ class FunctionDeclaration extends FunctionNode {
|
|
|
9669
9822
|
this.id.variable.isId = true;
|
|
9670
9823
|
}
|
|
9671
9824
|
}
|
|
9825
|
+
onlyFunctionCallUsed() {
|
|
9826
|
+
// call super.onlyFunctionCallUsed for export default anonymous function
|
|
9827
|
+
return this.id?.variable.getOnlyFunctionCallUsed() ?? super.onlyFunctionCallUsed();
|
|
9828
|
+
}
|
|
9672
9829
|
parseNode(esTreeNode) {
|
|
9673
9830
|
if (esTreeNode.id !== null) {
|
|
9674
9831
|
this.id = new Identifier(this, this.scope.parent).parseNode(esTreeNode.id);
|
|
@@ -9930,6 +10087,12 @@ class FunctionExpression extends FunctionNode {
|
|
|
9930
10087
|
}
|
|
9931
10088
|
return super.parseNode(esTreeNode);
|
|
9932
10089
|
}
|
|
10090
|
+
onlyFunctionCallUsed() {
|
|
10091
|
+
const isIIFE = this.parent.type === CallExpression$1 &&
|
|
10092
|
+
this.parent.callee === this &&
|
|
10093
|
+
(this.id === null || this.id.variable.getOnlyFunctionCallUsed());
|
|
10094
|
+
return isIIFE || super.onlyFunctionCallUsed();
|
|
10095
|
+
}
|
|
9933
10096
|
render(code, options, { renderedSurroundingElement } = BLANK) {
|
|
9934
10097
|
super.render(code, options);
|
|
9935
10098
|
if (renderedSurroundingElement === ExpressionStatement$1) {
|
|
@@ -11023,21 +11186,17 @@ const importMetaMechanisms = {
|
|
|
11023
11186
|
|
|
11024
11187
|
class NewExpression extends NodeBase {
|
|
11025
11188
|
hasEffects(context) {
|
|
11026
|
-
|
|
11027
|
-
|
|
11028
|
-
|
|
11029
|
-
|
|
11030
|
-
|
|
11031
|
-
if (this.annotationPure) {
|
|
11032
|
-
return false;
|
|
11033
|
-
}
|
|
11034
|
-
return (this.callee.hasEffects(context) ||
|
|
11035
|
-
this.callee.hasEffectsOnInteractionAtPath(EMPTY_PATH, this.interaction, context));
|
|
11189
|
+
if (!this.deoptimized)
|
|
11190
|
+
this.applyDeoptimizations();
|
|
11191
|
+
for (const argument of this.arguments) {
|
|
11192
|
+
if (argument.hasEffects(context))
|
|
11193
|
+
return true;
|
|
11036
11194
|
}
|
|
11037
|
-
|
|
11038
|
-
|
|
11039
|
-
this.applyDeoptimizations();
|
|
11195
|
+
if (this.annotationPure) {
|
|
11196
|
+
return false;
|
|
11040
11197
|
}
|
|
11198
|
+
return (this.callee.hasEffects(context) ||
|
|
11199
|
+
this.callee.hasEffectsOnInteractionAtPath(EMPTY_PATH, this.interaction, context));
|
|
11041
11200
|
}
|
|
11042
11201
|
hasEffectsOnInteractionAtPath(path, { type }) {
|
|
11043
11202
|
return path.length > 0 || type !== INTERACTION_ACCESSED;
|
|
@@ -11594,18 +11753,14 @@ class TaggedTemplateExpression extends CallExpressionBase {
|
|
|
11594
11753
|
}
|
|
11595
11754
|
}
|
|
11596
11755
|
hasEffects(context) {
|
|
11597
|
-
|
|
11598
|
-
|
|
11599
|
-
|
|
11600
|
-
|
|
11601
|
-
|
|
11602
|
-
return (this.tag.hasEffects(context) ||
|
|
11603
|
-
this.tag.hasEffectsOnInteractionAtPath(EMPTY_PATH, this.interaction, context));
|
|
11604
|
-
}
|
|
11605
|
-
finally {
|
|
11606
|
-
if (!this.deoptimized)
|
|
11607
|
-
this.applyDeoptimizations();
|
|
11756
|
+
if (!this.deoptimized)
|
|
11757
|
+
this.applyDeoptimizations();
|
|
11758
|
+
for (const argument of this.quasi.expressions) {
|
|
11759
|
+
if (argument.hasEffects(context))
|
|
11760
|
+
return true;
|
|
11608
11761
|
}
|
|
11762
|
+
return (this.tag.hasEffects(context) ||
|
|
11763
|
+
this.tag.hasEffectsOnInteractionAtPath(EMPTY_PATH, this.interaction, context));
|
|
11609
11764
|
}
|
|
11610
11765
|
include(context, includeChildrenRecursively) {
|
|
11611
11766
|
if (!this.deoptimized)
|
|
@@ -11735,6 +11890,15 @@ class ExportDefaultVariable extends LocalVariable {
|
|
|
11735
11890
|
this.name = identifier.name;
|
|
11736
11891
|
}
|
|
11737
11892
|
}
|
|
11893
|
+
addUsedPlace(usedPlace) {
|
|
11894
|
+
const original = this.getOriginalVariable();
|
|
11895
|
+
if (original === this) {
|
|
11896
|
+
super.addUsedPlace(usedPlace);
|
|
11897
|
+
}
|
|
11898
|
+
else {
|
|
11899
|
+
original.addUsedPlace(usedPlace);
|
|
11900
|
+
}
|
|
11901
|
+
}
|
|
11738
11902
|
forbidName(name) {
|
|
11739
11903
|
const original = this.getOriginalVariable();
|
|
11740
11904
|
if (original === this) {
|
|
@@ -12008,7 +12172,7 @@ class UpdateExpression extends NodeBase {
|
|
|
12008
12172
|
this.argument.deoptimizePath(EMPTY_PATH);
|
|
12009
12173
|
if (this.argument instanceof Identifier) {
|
|
12010
12174
|
const variable = this.scope.findVariable(this.argument.name);
|
|
12011
|
-
variable.
|
|
12175
|
+
variable.markReassigned();
|
|
12012
12176
|
}
|
|
12013
12177
|
this.scope.context.requestTreeshakingPass();
|
|
12014
12178
|
}
|
|
@@ -18125,7 +18289,7 @@ function addModuleToManualChunk(alias, module, manualChunkAliasByEntry) {
|
|
|
18125
18289
|
|
|
18126
18290
|
function flru (max) {
|
|
18127
18291
|
var num, curr, prev;
|
|
18128
|
-
var limit = max
|
|
18292
|
+
var limit = max ;
|
|
18129
18293
|
|
|
18130
18294
|
function keep(key, value) {
|
|
18131
18295
|
if (++num > limit) {
|