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