@rollup/wasm-node 4.16.4 → 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 +3 -4
- package/dist/es/getLogFilter.js +2 -2
- package/dist/es/parseAst.js +2 -2
- package/dist/es/rollup.js +2 -2
- package/dist/es/shared/node-entry.js +1097 -925
- package/dist/es/shared/parseAst.js +9 -7
- package/dist/es/shared/watch.js +2 -2
- package/dist/getLogFilter.js +2 -2
- package/dist/loadConfigFile.js +2 -2
- package/dist/parseAst.js +2 -2
- package/dist/rollup.js +2 -2
- package/dist/shared/fsevents-importer.js +2 -2
- package/dist/shared/index.js +2 -2
- package/dist/shared/loadConfigFile.js +2 -2
- package/dist/shared/parseAst.js +10 -6
- package/dist/shared/rollup.js +1087 -915
- 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
package/dist/shared/rollup.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
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
|
|
|
@@ -31,7 +31,7 @@ function _interopNamespaceDefault(e) {
|
|
|
31
31
|
|
|
32
32
|
const tty__namespace = /*#__PURE__*/_interopNamespaceDefault(tty);
|
|
33
33
|
|
|
34
|
-
var version = "4.
|
|
34
|
+
var version = "4.17.0";
|
|
35
35
|
|
|
36
36
|
function ensureArray$1(items) {
|
|
37
37
|
if (Array.isArray(items)) {
|
|
@@ -3393,6 +3393,9 @@ const NODE_INTERACTION_UNKNOWN_CALL = {
|
|
|
3393
3393
|
};
|
|
3394
3394
|
|
|
3395
3395
|
class Variable extends ExpressionEntity {
|
|
3396
|
+
markReassigned() {
|
|
3397
|
+
this.isReassigned = true;
|
|
3398
|
+
}
|
|
3396
3399
|
constructor(name) {
|
|
3397
3400
|
super();
|
|
3398
3401
|
this.name = name;
|
|
@@ -3400,16 +3403,35 @@ class Variable extends ExpressionEntity {
|
|
|
3400
3403
|
this.forbiddenNames = null;
|
|
3401
3404
|
this.initReached = false;
|
|
3402
3405
|
this.isId = false;
|
|
3403
|
-
this.isReassigned = false;
|
|
3404
3406
|
this.kind = null;
|
|
3405
3407
|
this.renderBaseName = null;
|
|
3406
3408
|
this.renderName = null;
|
|
3409
|
+
this.isReassigned = false;
|
|
3410
|
+
this.onlyFunctionCallUsed = true;
|
|
3407
3411
|
}
|
|
3408
3412
|
/**
|
|
3409
3413
|
* Binds identifiers that reference this variable to this variable.
|
|
3410
3414
|
* Necessary to be able to change variable names.
|
|
3411
3415
|
*/
|
|
3412
3416
|
addReference(_identifier) { }
|
|
3417
|
+
/**
|
|
3418
|
+
* Check if the identifier variable is only used as function call
|
|
3419
|
+
* @returns true if the variable is only used as function call
|
|
3420
|
+
*/
|
|
3421
|
+
getOnlyFunctionCallUsed() {
|
|
3422
|
+
return this.onlyFunctionCallUsed;
|
|
3423
|
+
}
|
|
3424
|
+
/**
|
|
3425
|
+
* Collect the places where the identifier variable is used
|
|
3426
|
+
* @param usedPlace Where the variable is used
|
|
3427
|
+
*/
|
|
3428
|
+
addUsedPlace(usedPlace) {
|
|
3429
|
+
const isFunctionCall = usedPlace.parent.type === parseAst_js.CallExpression &&
|
|
3430
|
+
usedPlace.parent.callee === usedPlace;
|
|
3431
|
+
if (!isFunctionCall && usedPlace.parent.type !== parseAst_js.ExportDefaultDeclaration) {
|
|
3432
|
+
this.onlyFunctionCallUsed = false;
|
|
3433
|
+
}
|
|
3434
|
+
}
|
|
3413
3435
|
/**
|
|
3414
3436
|
* Prevent this variable from being renamed to this name to avoid name
|
|
3415
3437
|
* collisions
|
|
@@ -7110,678 +7132,127 @@ class ArrayPattern extends NodeBase {
|
|
|
7110
7132
|
}
|
|
7111
7133
|
}
|
|
7112
7134
|
|
|
7113
|
-
|
|
7114
|
-
|
|
7115
|
-
|
|
7116
|
-
|
|
7117
|
-
|
|
7118
|
-
|
|
7119
|
-
|
|
7120
|
-
|
|
7121
|
-
|
|
7122
|
-
|
|
7123
|
-
|
|
7124
|
-
|
|
7125
|
-
|
|
7126
|
-
|
|
7127
|
-
|
|
7128
|
-
|
|
7129
|
-
|
|
7130
|
-
|
|
7131
|
-
|
|
7132
|
-
|
|
7133
|
-
|
|
7134
|
-
|
|
7135
|
-
|
|
7136
|
-
|
|
7137
|
-
|
|
7138
|
-
|
|
7139
|
-
|
|
7140
|
-
|
|
7141
|
-
|
|
7142
|
-
|
|
7143
|
-
|
|
7144
|
-
|
|
7145
|
-
|
|
7146
|
-
|
|
7147
|
-
|
|
7148
|
-
|
|
7149
|
-
|
|
7150
|
-
|
|
7151
|
-
|
|
7152
|
-
|
|
7153
|
-
|
|
7154
|
-
|
|
7155
|
-
|
|
7156
|
-
|
|
7157
|
-
|
|
7158
|
-
|
|
7159
|
-
|
|
7160
|
-
|
|
7161
|
-
|
|
7162
|
-
|
|
7163
|
-
|
|
7164
|
-
|
|
7165
|
-
|
|
7166
|
-
|
|
7167
|
-
|
|
7168
|
-
|
|
7169
|
-
|
|
7170
|
-
}
|
|
7171
|
-
getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin) {
|
|
7172
|
-
if (this.isReassigned) {
|
|
7173
|
-
return UNKNOWN_RETURN_EXPRESSION;
|
|
7174
|
-
}
|
|
7175
|
-
return recursionTracker.withTrackedEntityAtPath(path, this.init, () => {
|
|
7176
|
-
this.expressionsToBeDeoptimized.push(origin);
|
|
7177
|
-
return this.init.getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin);
|
|
7178
|
-
}, UNKNOWN_RETURN_EXPRESSION);
|
|
7179
|
-
}
|
|
7180
|
-
hasEffectsOnInteractionAtPath(path, interaction, context) {
|
|
7181
|
-
switch (interaction.type) {
|
|
7182
|
-
case INTERACTION_ACCESSED: {
|
|
7183
|
-
if (this.isReassigned)
|
|
7184
|
-
return true;
|
|
7185
|
-
return (!context.accessed.trackEntityAtPathAndGetIfTracked(path, this) &&
|
|
7186
|
-
this.init.hasEffectsOnInteractionAtPath(path, interaction, context));
|
|
7187
|
-
}
|
|
7188
|
-
case INTERACTION_ASSIGNED: {
|
|
7189
|
-
if (this.included)
|
|
7190
|
-
return true;
|
|
7191
|
-
if (path.length === 0)
|
|
7192
|
-
return false;
|
|
7193
|
-
if (this.isReassigned)
|
|
7194
|
-
return true;
|
|
7195
|
-
return (!context.assigned.trackEntityAtPathAndGetIfTracked(path, this) &&
|
|
7196
|
-
this.init.hasEffectsOnInteractionAtPath(path, interaction, context));
|
|
7197
|
-
}
|
|
7198
|
-
case INTERACTION_CALLED: {
|
|
7199
|
-
if (this.isReassigned)
|
|
7200
|
-
return true;
|
|
7201
|
-
return (!(interaction.withNew ? context.instantiated : context.called).trackEntityAtPathAndGetIfTracked(path, interaction.args, this) &&
|
|
7202
|
-
this.init.hasEffectsOnInteractionAtPath(path, interaction, context));
|
|
7203
|
-
}
|
|
7204
|
-
}
|
|
7205
|
-
}
|
|
7206
|
-
include() {
|
|
7207
|
-
if (!this.included) {
|
|
7208
|
-
super.include();
|
|
7209
|
-
for (const declaration of this.declarations) {
|
|
7210
|
-
// If node is a default export, it can save a tree-shaking run to include the full declaration now
|
|
7211
|
-
if (!declaration.included)
|
|
7212
|
-
declaration.include(createInclusionContext(), false);
|
|
7213
|
-
let node = declaration.parent;
|
|
7214
|
-
while (!node.included) {
|
|
7215
|
-
// We do not want to properly include parents in case they are part of a dead branch
|
|
7216
|
-
// in which case .include() might pull in more dead code
|
|
7217
|
-
node.included = true;
|
|
7218
|
-
if (node.type === parseAst_js.Program)
|
|
7219
|
-
break;
|
|
7220
|
-
node = node.parent;
|
|
7221
|
-
}
|
|
7222
|
-
}
|
|
7135
|
+
/** @typedef { import('estree').Node} Node */
|
|
7136
|
+
/** @typedef {Node | {
|
|
7137
|
+
* type: 'PropertyDefinition';
|
|
7138
|
+
* computed: boolean;
|
|
7139
|
+
* value: Node
|
|
7140
|
+
* }} NodeWithPropertyDefinition */
|
|
7141
|
+
|
|
7142
|
+
/**
|
|
7143
|
+
*
|
|
7144
|
+
* @param {NodeWithPropertyDefinition} node
|
|
7145
|
+
* @param {NodeWithPropertyDefinition} parent
|
|
7146
|
+
* @returns {boolean}
|
|
7147
|
+
*/
|
|
7148
|
+
function is_reference (node, parent) {
|
|
7149
|
+
if (node.type === 'MemberExpression') {
|
|
7150
|
+
return !node.computed && is_reference(node.object, node);
|
|
7151
|
+
}
|
|
7152
|
+
|
|
7153
|
+
if (node.type === 'Identifier') {
|
|
7154
|
+
if (!parent) return true;
|
|
7155
|
+
|
|
7156
|
+
switch (parent.type) {
|
|
7157
|
+
// disregard `bar` in `foo.bar`
|
|
7158
|
+
case 'MemberExpression': return parent.computed || node === parent.object;
|
|
7159
|
+
|
|
7160
|
+
// disregard the `foo` in `class {foo(){}}` but keep it in `class {[foo](){}}`
|
|
7161
|
+
case 'MethodDefinition': return parent.computed;
|
|
7162
|
+
|
|
7163
|
+
// disregard the `foo` in `class {foo=bar}` but keep it in `class {[foo]=bar}` and `class {bar=foo}`
|
|
7164
|
+
case 'PropertyDefinition': return parent.computed || node === parent.value;
|
|
7165
|
+
|
|
7166
|
+
// disregard the `bar` in `{ bar: foo }`, but keep it in `{ [bar]: foo }`
|
|
7167
|
+
case 'Property': return parent.computed || node === parent.value;
|
|
7168
|
+
|
|
7169
|
+
// disregard the `bar` in `export { foo as bar }` or
|
|
7170
|
+
// the foo in `import { foo as bar }`
|
|
7171
|
+
case 'ExportSpecifier':
|
|
7172
|
+
case 'ImportSpecifier': return node === parent.local;
|
|
7173
|
+
|
|
7174
|
+
// disregard the `foo` in `foo: while (...) { ... break foo; ... continue foo;}`
|
|
7175
|
+
case 'LabeledStatement':
|
|
7176
|
+
case 'BreakStatement':
|
|
7177
|
+
case 'ContinueStatement': return false;
|
|
7178
|
+
default: return true;
|
|
7179
|
+
}
|
|
7180
|
+
}
|
|
7181
|
+
|
|
7182
|
+
return false;
|
|
7183
|
+
}
|
|
7184
|
+
|
|
7185
|
+
const PureFunctionKey = Symbol('PureFunction');
|
|
7186
|
+
const getPureFunctions = ({ treeshake }) => {
|
|
7187
|
+
const pureFunctions = Object.create(null);
|
|
7188
|
+
for (const functionName of treeshake ? treeshake.manualPureFunctions : []) {
|
|
7189
|
+
let currentFunctions = pureFunctions;
|
|
7190
|
+
for (const pathSegment of functionName.split('.')) {
|
|
7191
|
+
currentFunctions = currentFunctions[pathSegment] ||= Object.create(null);
|
|
7223
7192
|
}
|
|
7193
|
+
currentFunctions[PureFunctionKey] = true;
|
|
7224
7194
|
}
|
|
7225
|
-
|
|
7226
|
-
|
|
7227
|
-
|
|
7228
|
-
|
|
7229
|
-
|
|
7230
|
-
|
|
7231
|
-
|
|
7232
|
-
|
|
7233
|
-
|
|
7234
|
-
|
|
7235
|
-
|
|
7195
|
+
return pureFunctions;
|
|
7196
|
+
};
|
|
7197
|
+
|
|
7198
|
+
/* eslint sort-keys: "off" */
|
|
7199
|
+
const ValueProperties = Symbol('Value Properties');
|
|
7200
|
+
const getTruthyLiteralValue = () => UnknownTruthyValue;
|
|
7201
|
+
const returnFalse = () => false;
|
|
7202
|
+
const returnTrue = () => true;
|
|
7203
|
+
const PURE = {
|
|
7204
|
+
deoptimizeArgumentsOnCall: doNothing,
|
|
7205
|
+
getLiteralValue: getTruthyLiteralValue,
|
|
7206
|
+
hasEffectsWhenCalled: returnFalse
|
|
7207
|
+
};
|
|
7208
|
+
const IMPURE = {
|
|
7209
|
+
deoptimizeArgumentsOnCall: doNothing,
|
|
7210
|
+
getLiteralValue: getTruthyLiteralValue,
|
|
7211
|
+
hasEffectsWhenCalled: returnTrue
|
|
7212
|
+
};
|
|
7213
|
+
const PURE_WITH_ARRAY = {
|
|
7214
|
+
deoptimizeArgumentsOnCall: doNothing,
|
|
7215
|
+
getLiteralValue: getTruthyLiteralValue,
|
|
7216
|
+
hasEffectsWhenCalled({ args }) {
|
|
7217
|
+
return args.length > 1 && !(args[1] instanceof ArrayExpression);
|
|
7236
7218
|
}
|
|
7237
|
-
|
|
7238
|
-
|
|
7219
|
+
};
|
|
7220
|
+
const GETTER_ACCESS = {
|
|
7221
|
+
deoptimizeArgumentsOnCall: doNothing,
|
|
7222
|
+
getLiteralValue: getTruthyLiteralValue,
|
|
7223
|
+
hasEffectsWhenCalled({ args }, context) {
|
|
7224
|
+
const [_thisArgument, firstArgument] = args;
|
|
7225
|
+
return (!(firstArgument instanceof ExpressionEntity) ||
|
|
7226
|
+
firstArgument.hasEffectsOnInteractionAtPath(UNKNOWN_PATH, NODE_INTERACTION_UNKNOWN_ACCESS, context));
|
|
7239
7227
|
}
|
|
7240
|
-
|
|
7241
|
-
|
|
7242
|
-
|
|
7243
|
-
|
|
7244
|
-
|
|
7245
|
-
|
|
7246
|
-
|
|
7247
|
-
|
|
7248
|
-
|
|
7249
|
-
|
|
7250
|
-
|
|
7251
|
-
|
|
7252
|
-
|
|
7253
|
-
const
|
|
7254
|
-
|
|
7255
|
-
|
|
7256
|
-
|
|
7257
|
-
|
|
7258
|
-
|
|
7259
|
-
|
|
7260
|
-
|
|
7261
|
-
|
|
7262
|
-
|
|
7263
|
-
|
|
7264
|
-
|
|
7265
|
-
|
|
7266
|
-
|
|
7267
|
-
|
|
7268
|
-
if (!this.entitiesToBeDeoptimized.has(UNKNOWN_EXPRESSION)) {
|
|
7269
|
-
this.entitiesToBeDeoptimized.add(UNKNOWN_EXPRESSION);
|
|
7270
|
-
for (const { interaction } of this.deoptimizationInteractions) {
|
|
7271
|
-
deoptimizeInteraction(interaction);
|
|
7272
|
-
}
|
|
7273
|
-
this.deoptimizationInteractions = NO_INTERACTIONS;
|
|
7274
|
-
}
|
|
7275
|
-
}
|
|
7276
|
-
else if (this.deoptimizedFields.has(UnknownKey)) {
|
|
7277
|
-
// This means that we already deoptimized all interactions and no longer
|
|
7278
|
-
// track them
|
|
7279
|
-
entity.deoptimizePath(UNKNOWN_PATH);
|
|
7280
|
-
}
|
|
7281
|
-
else if (!this.entitiesToBeDeoptimized.has(entity)) {
|
|
7282
|
-
this.entitiesToBeDeoptimized.add(entity);
|
|
7283
|
-
for (const field of this.deoptimizedFields) {
|
|
7284
|
-
entity.deoptimizePath([field]);
|
|
7285
|
-
}
|
|
7286
|
-
for (const { interaction, path } of this.deoptimizationInteractions) {
|
|
7287
|
-
entity.deoptimizeArgumentsOnInteractionAtPath(interaction, path, SHARED_RECURSION_TRACKER);
|
|
7288
|
-
}
|
|
7289
|
-
}
|
|
7290
|
-
}
|
|
7291
|
-
deoptimizeArgumentsOnInteractionAtPath(interaction, path) {
|
|
7292
|
-
// For performance reasons, we fully deoptimize all deeper interactions
|
|
7293
|
-
if (path.length >= 2 ||
|
|
7294
|
-
this.entitiesToBeDeoptimized.has(UNKNOWN_EXPRESSION) ||
|
|
7295
|
-
this.deoptimizationInteractions.length >= MAX_TRACKED_INTERACTIONS ||
|
|
7296
|
-
(path.length === 1 &&
|
|
7297
|
-
(this.deoptimizedFields.has(UnknownKey) ||
|
|
7298
|
-
(interaction.type === INTERACTION_CALLED && this.deoptimizedFields.has(path[0]))))) {
|
|
7299
|
-
deoptimizeInteraction(interaction);
|
|
7300
|
-
return;
|
|
7301
|
-
}
|
|
7302
|
-
if (!this.deoptimizations.trackEntityAtPathAndGetIfTracked(path, interaction.args)) {
|
|
7303
|
-
for (const entity of this.entitiesToBeDeoptimized) {
|
|
7304
|
-
entity.deoptimizeArgumentsOnInteractionAtPath(interaction, path, SHARED_RECURSION_TRACKER);
|
|
7305
|
-
}
|
|
7306
|
-
if (!this.entitiesToBeDeoptimized.has(UNKNOWN_EXPRESSION)) {
|
|
7307
|
-
this.deoptimizationInteractions.push({
|
|
7308
|
-
interaction,
|
|
7309
|
-
path
|
|
7310
|
-
});
|
|
7311
|
-
}
|
|
7312
|
-
}
|
|
7313
|
-
}
|
|
7314
|
-
deoptimizePath(path) {
|
|
7315
|
-
if (path.length === 0 || this.deoptimizedFields.has(UnknownKey)) {
|
|
7316
|
-
return;
|
|
7317
|
-
}
|
|
7318
|
-
const key = path[0];
|
|
7319
|
-
if (this.deoptimizedFields.has(key)) {
|
|
7320
|
-
return;
|
|
7321
|
-
}
|
|
7322
|
-
this.deoptimizedFields.add(key);
|
|
7323
|
-
for (const entity of this.entitiesToBeDeoptimized) {
|
|
7324
|
-
// We do not need a recursion tracker here as we already track whether
|
|
7325
|
-
// this field is deoptimized
|
|
7326
|
-
entity.deoptimizePath([key]);
|
|
7327
|
-
}
|
|
7328
|
-
if (key === UnknownKey) {
|
|
7329
|
-
// save some memory
|
|
7330
|
-
this.deoptimizationInteractions = NO_INTERACTIONS;
|
|
7331
|
-
this.deoptimizations = EMPTY_PATH_TRACKER;
|
|
7332
|
-
this.deoptimizedFields = UNKNOWN_DEOPTIMIZED_FIELD;
|
|
7333
|
-
this.entitiesToBeDeoptimized = UNKNOWN_DEOPTIMIZED_ENTITY;
|
|
7334
|
-
}
|
|
7335
|
-
}
|
|
7336
|
-
getReturnExpressionWhenCalledAtPath(path) {
|
|
7337
|
-
// We deoptimize everything that is called as that will trivially deoptimize
|
|
7338
|
-
// the corresponding return expressions as well and avoid badly performing
|
|
7339
|
-
// and complicated alternatives
|
|
7340
|
-
if (path.length === 0) {
|
|
7341
|
-
this.deoptimizePath(UNKNOWN_PATH);
|
|
7342
|
-
}
|
|
7343
|
-
else if (!this.deoptimizedFields.has(path[0])) {
|
|
7344
|
-
this.deoptimizePath([path[0]]);
|
|
7345
|
-
}
|
|
7346
|
-
return UNKNOWN_RETURN_EXPRESSION;
|
|
7347
|
-
}
|
|
7348
|
-
}
|
|
7349
|
-
|
|
7350
|
-
function getSafeName(baseName, usedNames, forbiddenNames) {
|
|
7351
|
-
let safeName = baseName;
|
|
7352
|
-
let count = 1;
|
|
7353
|
-
while (usedNames.has(safeName) || RESERVED_NAMES.has(safeName) || forbiddenNames?.has(safeName)) {
|
|
7354
|
-
safeName = `${baseName}$${toBase64(count++)}`;
|
|
7355
|
-
}
|
|
7356
|
-
usedNames.add(safeName);
|
|
7357
|
-
return safeName;
|
|
7358
|
-
}
|
|
7359
|
-
|
|
7360
|
-
class Scope {
|
|
7361
|
-
constructor() {
|
|
7362
|
-
this.children = [];
|
|
7363
|
-
this.variables = new Map();
|
|
7364
|
-
}
|
|
7365
|
-
/*
|
|
7366
|
-
Redeclaration rules:
|
|
7367
|
-
- var can redeclare var
|
|
7368
|
-
- in function scopes, function and var can redeclare function and var
|
|
7369
|
-
- var is hoisted across scopes, function remains in the scope it is declared
|
|
7370
|
-
- var and function can redeclare function parameters, but parameters cannot redeclare parameters
|
|
7371
|
-
- function cannot redeclare catch scope parameters
|
|
7372
|
-
- var can redeclare catch scope parameters in a way
|
|
7373
|
-
- if the parameter is an identifier and not a pattern
|
|
7374
|
-
- then the variable is still declared in the hoisted outer scope, but the initializer is assigned to the parameter
|
|
7375
|
-
- const, let, class, and function except in the cases above cannot redeclare anything
|
|
7376
|
-
*/
|
|
7377
|
-
addDeclaration(identifier, context, init, kind) {
|
|
7378
|
-
const name = identifier.name;
|
|
7379
|
-
const existingVariable = this.hoistedVariables?.get(name) || this.variables.get(name);
|
|
7380
|
-
if (existingVariable) {
|
|
7381
|
-
const existingKind = existingVariable.kind;
|
|
7382
|
-
if (kind === 'var' && existingKind === 'var') {
|
|
7383
|
-
existingVariable.addDeclaration(identifier, init);
|
|
7384
|
-
return existingVariable;
|
|
7385
|
-
}
|
|
7386
|
-
context.error(parseAst_js.logRedeclarationError(name), identifier.start);
|
|
7387
|
-
}
|
|
7388
|
-
const newVariable = new LocalVariable(identifier.name, identifier, init, context, kind);
|
|
7389
|
-
this.variables.set(name, newVariable);
|
|
7390
|
-
return newVariable;
|
|
7391
|
-
}
|
|
7392
|
-
addHoistedVariable(name, variable) {
|
|
7393
|
-
(this.hoistedVariables ||= new Map()).set(name, variable);
|
|
7394
|
-
}
|
|
7395
|
-
contains(name) {
|
|
7396
|
-
return this.variables.has(name);
|
|
7397
|
-
}
|
|
7398
|
-
findVariable(_name) {
|
|
7399
|
-
/* istanbul ignore next */
|
|
7400
|
-
throw new Error('Internal Error: findVariable needs to be implemented by a subclass');
|
|
7401
|
-
}
|
|
7402
|
-
}
|
|
7403
|
-
|
|
7404
|
-
class ChildScope extends Scope {
|
|
7405
|
-
constructor(parent, context) {
|
|
7406
|
-
super();
|
|
7407
|
-
this.parent = parent;
|
|
7408
|
-
this.context = context;
|
|
7409
|
-
this.accessedOutsideVariables = new Map();
|
|
7410
|
-
parent.children.push(this);
|
|
7411
|
-
}
|
|
7412
|
-
addAccessedDynamicImport(importExpression) {
|
|
7413
|
-
(this.accessedDynamicImports || (this.accessedDynamicImports = new Set())).add(importExpression);
|
|
7414
|
-
if (this.parent instanceof ChildScope) {
|
|
7415
|
-
this.parent.addAccessedDynamicImport(importExpression);
|
|
7416
|
-
}
|
|
7417
|
-
}
|
|
7418
|
-
addAccessedGlobals(globals, accessedGlobalsByScope) {
|
|
7419
|
-
const accessedGlobals = accessedGlobalsByScope.get(this) || new Set();
|
|
7420
|
-
for (const name of globals) {
|
|
7421
|
-
accessedGlobals.add(name);
|
|
7422
|
-
}
|
|
7423
|
-
accessedGlobalsByScope.set(this, accessedGlobals);
|
|
7424
|
-
if (this.parent instanceof ChildScope) {
|
|
7425
|
-
this.parent.addAccessedGlobals(globals, accessedGlobalsByScope);
|
|
7426
|
-
}
|
|
7427
|
-
}
|
|
7428
|
-
addNamespaceMemberAccess(name, variable) {
|
|
7429
|
-
this.accessedOutsideVariables.set(name, variable);
|
|
7430
|
-
this.parent.addNamespaceMemberAccess(name, variable);
|
|
7431
|
-
}
|
|
7432
|
-
addReturnExpression(expression) {
|
|
7433
|
-
this.parent instanceof ChildScope && this.parent.addReturnExpression(expression);
|
|
7434
|
-
}
|
|
7435
|
-
addUsedOutsideNames(usedNames, format, exportNamesByVariable, accessedGlobalsByScope) {
|
|
7436
|
-
for (const variable of this.accessedOutsideVariables.values()) {
|
|
7437
|
-
if (variable.included) {
|
|
7438
|
-
usedNames.add(variable.getBaseVariableName());
|
|
7439
|
-
if (format === 'system' && exportNamesByVariable.has(variable)) {
|
|
7440
|
-
usedNames.add('exports');
|
|
7441
|
-
}
|
|
7442
|
-
}
|
|
7443
|
-
}
|
|
7444
|
-
const accessedGlobals = accessedGlobalsByScope.get(this);
|
|
7445
|
-
if (accessedGlobals) {
|
|
7446
|
-
for (const name of accessedGlobals) {
|
|
7447
|
-
usedNames.add(name);
|
|
7448
|
-
}
|
|
7449
|
-
}
|
|
7450
|
-
}
|
|
7451
|
-
contains(name) {
|
|
7452
|
-
return this.variables.has(name) || this.parent.contains(name);
|
|
7453
|
-
}
|
|
7454
|
-
deconflict(format, exportNamesByVariable, accessedGlobalsByScope) {
|
|
7455
|
-
const usedNames = new Set();
|
|
7456
|
-
this.addUsedOutsideNames(usedNames, format, exportNamesByVariable, accessedGlobalsByScope);
|
|
7457
|
-
if (this.accessedDynamicImports) {
|
|
7458
|
-
for (const importExpression of this.accessedDynamicImports) {
|
|
7459
|
-
if (importExpression.inlineNamespace) {
|
|
7460
|
-
usedNames.add(importExpression.inlineNamespace.getBaseVariableName());
|
|
7461
|
-
}
|
|
7462
|
-
}
|
|
7463
|
-
}
|
|
7464
|
-
for (const [name, variable] of this.variables) {
|
|
7465
|
-
if (variable.included || variable.alwaysRendered) {
|
|
7466
|
-
variable.setRenderNames(null, getSafeName(name, usedNames, variable.forbiddenNames));
|
|
7467
|
-
}
|
|
7468
|
-
}
|
|
7469
|
-
for (const scope of this.children) {
|
|
7470
|
-
scope.deconflict(format, exportNamesByVariable, accessedGlobalsByScope);
|
|
7471
|
-
}
|
|
7472
|
-
}
|
|
7473
|
-
findLexicalBoundary() {
|
|
7474
|
-
return this.parent.findLexicalBoundary();
|
|
7475
|
-
}
|
|
7476
|
-
findVariable(name) {
|
|
7477
|
-
const knownVariable = this.variables.get(name) || this.accessedOutsideVariables.get(name);
|
|
7478
|
-
if (knownVariable) {
|
|
7479
|
-
return knownVariable;
|
|
7480
|
-
}
|
|
7481
|
-
const variable = this.parent.findVariable(name);
|
|
7482
|
-
this.accessedOutsideVariables.set(name, variable);
|
|
7483
|
-
return variable;
|
|
7484
|
-
}
|
|
7485
|
-
}
|
|
7486
|
-
|
|
7487
|
-
class CatchBodyScope extends ChildScope {
|
|
7488
|
-
constructor(parent) {
|
|
7489
|
-
super(parent, parent.context);
|
|
7490
|
-
this.parent = parent;
|
|
7491
|
-
}
|
|
7492
|
-
addDeclaration(identifier, context, init, kind) {
|
|
7493
|
-
if (kind === 'var') {
|
|
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 (existingKind === 'parameter' &&
|
|
7499
|
-
// If this is a destructured parameter, it is forbidden to redeclare
|
|
7500
|
-
existingVariable.declarations[0].parent.type === parseAst_js.CatchClause) {
|
|
7501
|
-
// If this is a var with the same name as the catch scope parameter,
|
|
7502
|
-
// the assignment actually goes to the parameter and the var is
|
|
7503
|
-
// hoisted without assignment. Locally, it is shadowed by the
|
|
7504
|
-
// parameter
|
|
7505
|
-
const declaredVariable = this.parent.parent.addDeclaration(identifier, context, UNDEFINED_EXPRESSION, kind);
|
|
7506
|
-
// To avoid the need to rewrite the declaration, we link the variable
|
|
7507
|
-
// names. If we ever implement a logic that splits initialization and
|
|
7508
|
-
// assignment for hoisted vars, the "renderLikeHoisted" logic can be
|
|
7509
|
-
// removed again.
|
|
7510
|
-
// We do not need to check whether there already is a linked
|
|
7511
|
-
// variable because then declaredVariable would be that linked
|
|
7512
|
-
// variable.
|
|
7513
|
-
existingVariable.renderLikeHoisted(declaredVariable);
|
|
7514
|
-
this.addHoistedVariable(name, declaredVariable);
|
|
7515
|
-
return declaredVariable;
|
|
7516
|
-
}
|
|
7517
|
-
if (existingKind === 'var') {
|
|
7518
|
-
existingVariable.addDeclaration(identifier, init);
|
|
7519
|
-
return existingVariable;
|
|
7520
|
-
}
|
|
7521
|
-
return context.error(parseAst_js.logRedeclarationError(name), identifier.start);
|
|
7522
|
-
}
|
|
7523
|
-
// We only add parameters to parameter scopes
|
|
7524
|
-
const declaredVariable = this.parent.parent.addDeclaration(identifier, context, init, kind);
|
|
7525
|
-
// Necessary to make sure the init is deoptimized for conditional declarations.
|
|
7526
|
-
// We cannot call deoptimizePath here.
|
|
7527
|
-
declaredVariable.markInitializersForDeoptimization();
|
|
7528
|
-
// We add the variable to this and all parent scopes to reliably detect conflicts
|
|
7529
|
-
this.addHoistedVariable(name, declaredVariable);
|
|
7530
|
-
return declaredVariable;
|
|
7531
|
-
}
|
|
7532
|
-
return super.addDeclaration(identifier, context, init, kind);
|
|
7533
|
-
}
|
|
7534
|
-
}
|
|
7535
|
-
|
|
7536
|
-
class FunctionBodyScope extends ChildScope {
|
|
7537
|
-
constructor(parent) {
|
|
7538
|
-
super(parent, parent.context);
|
|
7539
|
-
}
|
|
7540
|
-
// There is stuff that is only allowed in function scopes, i.e. functions can
|
|
7541
|
-
// be redeclared, functions and var can redeclare each other
|
|
7542
|
-
addDeclaration(identifier, context, init, kind) {
|
|
7543
|
-
const name = identifier.name;
|
|
7544
|
-
const existingVariable = this.hoistedVariables?.get(name) || this.variables.get(name);
|
|
7545
|
-
if (existingVariable) {
|
|
7546
|
-
const existingKind = existingVariable.kind;
|
|
7547
|
-
if ((kind === 'var' || kind === 'function') &&
|
|
7548
|
-
(existingKind === 'var' || existingKind === 'function' || existingKind === 'parameter')) {
|
|
7549
|
-
existingVariable.addDeclaration(identifier, init);
|
|
7550
|
-
return existingVariable;
|
|
7551
|
-
}
|
|
7552
|
-
context.error(parseAst_js.logRedeclarationError(name), identifier.start);
|
|
7553
|
-
}
|
|
7554
|
-
const newVariable = new LocalVariable(identifier.name, identifier, init, context, kind);
|
|
7555
|
-
this.variables.set(name, newVariable);
|
|
7556
|
-
return newVariable;
|
|
7557
|
-
}
|
|
7558
|
-
}
|
|
7559
|
-
|
|
7560
|
-
class ParameterScope extends ChildScope {
|
|
7561
|
-
constructor(parent, isCatchScope) {
|
|
7562
|
-
super(parent, parent.context);
|
|
7563
|
-
this.parameters = [];
|
|
7564
|
-
this.hasRest = false;
|
|
7565
|
-
this.bodyScope = isCatchScope ? new CatchBodyScope(this) : new FunctionBodyScope(this);
|
|
7566
|
-
}
|
|
7567
|
-
/**
|
|
7568
|
-
* Adds a parameter to this scope. Parameters must be added in the correct
|
|
7569
|
-
* order, i.e. from left to right.
|
|
7570
|
-
*/
|
|
7571
|
-
addParameterDeclaration(identifier) {
|
|
7572
|
-
const { name, start } = identifier;
|
|
7573
|
-
const existingParameter = this.variables.get(name);
|
|
7574
|
-
if (existingParameter) {
|
|
7575
|
-
return this.context.error(parseAst_js.logDuplicateArgumentNameError(name), start);
|
|
7576
|
-
}
|
|
7577
|
-
const variable = new ParameterVariable(name, identifier, this.context);
|
|
7578
|
-
this.variables.set(name, variable);
|
|
7579
|
-
// We also add it to the body scope to detect name conflicts with local
|
|
7580
|
-
// variables. We still need the intermediate scope, though, as parameter
|
|
7581
|
-
// defaults are NOT taken from the body scope but from the parameters or
|
|
7582
|
-
// outside scope.
|
|
7583
|
-
this.bodyScope.addHoistedVariable(name, variable);
|
|
7584
|
-
return variable;
|
|
7585
|
-
}
|
|
7586
|
-
addParameterVariables(parameters, hasRest) {
|
|
7587
|
-
this.parameters = parameters;
|
|
7588
|
-
for (const parameterList of parameters) {
|
|
7589
|
-
for (const parameter of parameterList) {
|
|
7590
|
-
parameter.alwaysRendered = true;
|
|
7591
|
-
}
|
|
7592
|
-
}
|
|
7593
|
-
this.hasRest = hasRest;
|
|
7594
|
-
}
|
|
7595
|
-
includeCallArguments(context, parameters) {
|
|
7596
|
-
let calledFromTryStatement = false;
|
|
7597
|
-
let argumentIncluded = false;
|
|
7598
|
-
const restParameter = this.hasRest && this.parameters[this.parameters.length - 1];
|
|
7599
|
-
for (const checkedArgument of parameters) {
|
|
7600
|
-
if (checkedArgument instanceof SpreadElement) {
|
|
7601
|
-
for (const argument of parameters) {
|
|
7602
|
-
argument.include(context, false);
|
|
7603
|
-
}
|
|
7604
|
-
break;
|
|
7605
|
-
}
|
|
7606
|
-
}
|
|
7607
|
-
for (let index = parameters.length - 1; index >= 0; index--) {
|
|
7608
|
-
const parameterVariables = this.parameters[index] || restParameter;
|
|
7609
|
-
const argument = parameters[index];
|
|
7610
|
-
if (parameterVariables) {
|
|
7611
|
-
calledFromTryStatement = false;
|
|
7612
|
-
if (parameterVariables.length === 0) {
|
|
7613
|
-
// handle empty destructuring
|
|
7614
|
-
argumentIncluded = true;
|
|
7615
|
-
}
|
|
7616
|
-
else {
|
|
7617
|
-
for (const variable of parameterVariables) {
|
|
7618
|
-
if (variable.included) {
|
|
7619
|
-
argumentIncluded = true;
|
|
7620
|
-
}
|
|
7621
|
-
if (variable.calledFromTryStatement) {
|
|
7622
|
-
calledFromTryStatement = true;
|
|
7623
|
-
}
|
|
7624
|
-
}
|
|
7625
|
-
}
|
|
7626
|
-
}
|
|
7627
|
-
if (!argumentIncluded && argument.shouldBeIncluded(context)) {
|
|
7628
|
-
argumentIncluded = true;
|
|
7629
|
-
}
|
|
7630
|
-
if (argumentIncluded) {
|
|
7631
|
-
argument.include(context, calledFromTryStatement);
|
|
7632
|
-
}
|
|
7633
|
-
}
|
|
7634
|
-
}
|
|
7635
|
-
}
|
|
7636
|
-
|
|
7637
|
-
class ReturnValueScope extends ParameterScope {
|
|
7638
|
-
constructor() {
|
|
7639
|
-
super(...arguments);
|
|
7640
|
-
this.returnExpression = null;
|
|
7641
|
-
this.returnExpressions = [];
|
|
7642
|
-
}
|
|
7643
|
-
addReturnExpression(expression) {
|
|
7644
|
-
this.returnExpressions.push(expression);
|
|
7645
|
-
}
|
|
7646
|
-
getReturnExpression() {
|
|
7647
|
-
if (this.returnExpression === null)
|
|
7648
|
-
this.updateReturnExpression();
|
|
7649
|
-
return this.returnExpression;
|
|
7650
|
-
}
|
|
7651
|
-
updateReturnExpression() {
|
|
7652
|
-
if (this.returnExpressions.length === 1) {
|
|
7653
|
-
this.returnExpression = this.returnExpressions[0];
|
|
7654
|
-
}
|
|
7655
|
-
else {
|
|
7656
|
-
this.returnExpression = UNKNOWN_EXPRESSION;
|
|
7657
|
-
for (const expression of this.returnExpressions) {
|
|
7658
|
-
expression.deoptimizePath(UNKNOWN_PATH);
|
|
7659
|
-
}
|
|
7660
|
-
}
|
|
7661
|
-
}
|
|
7662
|
-
}
|
|
7663
|
-
|
|
7664
|
-
/** @typedef { import('estree').Node} Node */
|
|
7665
|
-
/** @typedef {Node | {
|
|
7666
|
-
* type: 'PropertyDefinition';
|
|
7667
|
-
* computed: boolean;
|
|
7668
|
-
* value: Node
|
|
7669
|
-
* }} NodeWithPropertyDefinition */
|
|
7670
|
-
|
|
7671
|
-
/**
|
|
7672
|
-
*
|
|
7673
|
-
* @param {NodeWithPropertyDefinition} node
|
|
7674
|
-
* @param {NodeWithPropertyDefinition} parent
|
|
7675
|
-
* @returns {boolean}
|
|
7676
|
-
*/
|
|
7677
|
-
function is_reference (node, parent) {
|
|
7678
|
-
if (node.type === 'MemberExpression') {
|
|
7679
|
-
return !node.computed && is_reference(node.object, node);
|
|
7680
|
-
}
|
|
7681
|
-
|
|
7682
|
-
if (node.type === 'Identifier') {
|
|
7683
|
-
if (!parent) return true;
|
|
7684
|
-
|
|
7685
|
-
switch (parent.type) {
|
|
7686
|
-
// disregard `bar` in `foo.bar`
|
|
7687
|
-
case 'MemberExpression': return parent.computed || node === parent.object;
|
|
7688
|
-
|
|
7689
|
-
// disregard the `foo` in `class {foo(){}}` but keep it in `class {[foo](){}}`
|
|
7690
|
-
case 'MethodDefinition': return parent.computed;
|
|
7691
|
-
|
|
7692
|
-
// disregard the `foo` in `class {foo=bar}` but keep it in `class {[foo]=bar}` and `class {bar=foo}`
|
|
7693
|
-
case 'PropertyDefinition': return parent.computed || node === parent.value;
|
|
7694
|
-
|
|
7695
|
-
// disregard the `bar` in `{ bar: foo }`, but keep it in `{ [bar]: foo }`
|
|
7696
|
-
case 'Property': return parent.computed || node === parent.value;
|
|
7697
|
-
|
|
7698
|
-
// disregard the `bar` in `export { foo as bar }` or
|
|
7699
|
-
// the foo in `import { foo as bar }`
|
|
7700
|
-
case 'ExportSpecifier':
|
|
7701
|
-
case 'ImportSpecifier': return node === parent.local;
|
|
7702
|
-
|
|
7703
|
-
// disregard the `foo` in `foo: while (...) { ... break foo; ... continue foo;}`
|
|
7704
|
-
case 'LabeledStatement':
|
|
7705
|
-
case 'BreakStatement':
|
|
7706
|
-
case 'ContinueStatement': return false;
|
|
7707
|
-
default: return true;
|
|
7708
|
-
}
|
|
7709
|
-
}
|
|
7710
|
-
|
|
7711
|
-
return false;
|
|
7712
|
-
}
|
|
7713
|
-
|
|
7714
|
-
const PureFunctionKey = Symbol('PureFunction');
|
|
7715
|
-
const getPureFunctions = ({ treeshake }) => {
|
|
7716
|
-
const pureFunctions = Object.create(null);
|
|
7717
|
-
for (const functionName of treeshake ? treeshake.manualPureFunctions : []) {
|
|
7718
|
-
let currentFunctions = pureFunctions;
|
|
7719
|
-
for (const pathSegment of functionName.split('.')) {
|
|
7720
|
-
currentFunctions = currentFunctions[pathSegment] ||= Object.create(null);
|
|
7721
|
-
}
|
|
7722
|
-
currentFunctions[PureFunctionKey] = true;
|
|
7723
|
-
}
|
|
7724
|
-
return pureFunctions;
|
|
7725
|
-
};
|
|
7726
|
-
|
|
7727
|
-
/* eslint sort-keys: "off" */
|
|
7728
|
-
const ValueProperties = Symbol('Value Properties');
|
|
7729
|
-
const getTruthyLiteralValue = () => UnknownTruthyValue;
|
|
7730
|
-
const returnFalse = () => false;
|
|
7731
|
-
const returnTrue = () => true;
|
|
7732
|
-
const PURE = {
|
|
7733
|
-
deoptimizeArgumentsOnCall: doNothing,
|
|
7734
|
-
getLiteralValue: getTruthyLiteralValue,
|
|
7735
|
-
hasEffectsWhenCalled: returnFalse
|
|
7736
|
-
};
|
|
7737
|
-
const IMPURE = {
|
|
7738
|
-
deoptimizeArgumentsOnCall: doNothing,
|
|
7739
|
-
getLiteralValue: getTruthyLiteralValue,
|
|
7740
|
-
hasEffectsWhenCalled: returnTrue
|
|
7741
|
-
};
|
|
7742
|
-
const PURE_WITH_ARRAY = {
|
|
7743
|
-
deoptimizeArgumentsOnCall: doNothing,
|
|
7744
|
-
getLiteralValue: getTruthyLiteralValue,
|
|
7745
|
-
hasEffectsWhenCalled({ args }) {
|
|
7746
|
-
return args.length > 1 && !(args[1] instanceof ArrayExpression);
|
|
7747
|
-
}
|
|
7748
|
-
};
|
|
7749
|
-
const GETTER_ACCESS = {
|
|
7750
|
-
deoptimizeArgumentsOnCall: doNothing,
|
|
7751
|
-
getLiteralValue: getTruthyLiteralValue,
|
|
7752
|
-
hasEffectsWhenCalled({ args }, context) {
|
|
7753
|
-
const [_thisArgument, firstArgument] = args;
|
|
7754
|
-
return (!(firstArgument instanceof ExpressionEntity) ||
|
|
7755
|
-
firstArgument.hasEffectsOnInteractionAtPath(UNKNOWN_PATH, NODE_INTERACTION_UNKNOWN_ACCESS, context));
|
|
7756
|
-
}
|
|
7757
|
-
};
|
|
7758
|
-
// We use shortened variables to reduce file size here
|
|
7759
|
-
/* OBJECT */
|
|
7760
|
-
const O = {
|
|
7761
|
-
__proto__: null,
|
|
7762
|
-
[ValueProperties]: IMPURE
|
|
7763
|
-
};
|
|
7764
|
-
/* PURE FUNCTION */
|
|
7765
|
-
const PF = {
|
|
7766
|
-
__proto__: null,
|
|
7767
|
-
[ValueProperties]: PURE
|
|
7768
|
-
};
|
|
7769
|
-
/* PURE FUNCTION IF FIRST ARG DOES NOT CONTAIN A GETTER */
|
|
7770
|
-
const PF_NO_GETTER = {
|
|
7771
|
-
__proto__: null,
|
|
7772
|
-
[ValueProperties]: GETTER_ACCESS
|
|
7773
|
-
};
|
|
7774
|
-
/* FUNCTION THAT MUTATES FIRST ARG WITHOUT TRIGGERING ACCESSORS */
|
|
7775
|
-
const MUTATES_ARG_WITHOUT_ACCESSOR = {
|
|
7776
|
-
__proto__: null,
|
|
7777
|
-
[ValueProperties]: {
|
|
7778
|
-
deoptimizeArgumentsOnCall({ args: [, firstArgument] }) {
|
|
7779
|
-
firstArgument?.deoptimizePath(UNKNOWN_PATH);
|
|
7780
|
-
},
|
|
7781
|
-
getLiteralValue: getTruthyLiteralValue,
|
|
7782
|
-
hasEffectsWhenCalled({ args }, context) {
|
|
7783
|
-
return (args.length <= 1 ||
|
|
7784
|
-
args[1].hasEffectsOnInteractionAtPath(UNKNOWN_NON_ACCESSOR_PATH, NODE_INTERACTION_UNKNOWN_ASSIGNMENT, context));
|
|
7228
|
+
};
|
|
7229
|
+
// We use shortened variables to reduce file size here
|
|
7230
|
+
/* OBJECT */
|
|
7231
|
+
const O = {
|
|
7232
|
+
__proto__: null,
|
|
7233
|
+
[ValueProperties]: IMPURE
|
|
7234
|
+
};
|
|
7235
|
+
/* PURE FUNCTION */
|
|
7236
|
+
const PF = {
|
|
7237
|
+
__proto__: null,
|
|
7238
|
+
[ValueProperties]: PURE
|
|
7239
|
+
};
|
|
7240
|
+
/* PURE FUNCTION IF FIRST ARG DOES NOT CONTAIN A GETTER */
|
|
7241
|
+
const PF_NO_GETTER = {
|
|
7242
|
+
__proto__: null,
|
|
7243
|
+
[ValueProperties]: GETTER_ACCESS
|
|
7244
|
+
};
|
|
7245
|
+
/* FUNCTION THAT MUTATES FIRST ARG WITHOUT TRIGGERING ACCESSORS */
|
|
7246
|
+
const MUTATES_ARG_WITHOUT_ACCESSOR = {
|
|
7247
|
+
__proto__: null,
|
|
7248
|
+
[ValueProperties]: {
|
|
7249
|
+
deoptimizeArgumentsOnCall({ args: [, firstArgument] }) {
|
|
7250
|
+
firstArgument?.deoptimizePath(UNKNOWN_PATH);
|
|
7251
|
+
},
|
|
7252
|
+
getLiteralValue: getTruthyLiteralValue,
|
|
7253
|
+
hasEffectsWhenCalled({ args }, context) {
|
|
7254
|
+
return (args.length <= 1 ||
|
|
7255
|
+
args[1].hasEffectsOnInteractionAtPath(UNKNOWN_NON_ACCESSOR_PATH, NODE_INTERACTION_UNKNOWN_ASSIGNMENT, context));
|
|
7785
7256
|
}
|
|
7786
7257
|
}
|
|
7787
7258
|
};
|
|
@@ -8659,290 +8130,928 @@ const knownGlobals = {
|
|
|
8659
8130
|
for (const global of ['window', 'global', 'self', 'globalThis']) {
|
|
8660
8131
|
knownGlobals[global] = knownGlobals;
|
|
8661
8132
|
}
|
|
8662
|
-
function getGlobalAtPath(path) {
|
|
8663
|
-
let currentGlobal = knownGlobals;
|
|
8664
|
-
for (const pathSegment of path) {
|
|
8665
|
-
if (typeof pathSegment !== 'string') {
|
|
8133
|
+
function getGlobalAtPath(path) {
|
|
8134
|
+
let currentGlobal = knownGlobals;
|
|
8135
|
+
for (const pathSegment of path) {
|
|
8136
|
+
if (typeof pathSegment !== 'string') {
|
|
8137
|
+
return null;
|
|
8138
|
+
}
|
|
8139
|
+
currentGlobal = currentGlobal[pathSegment];
|
|
8140
|
+
if (!currentGlobal) {
|
|
8141
|
+
return null;
|
|
8142
|
+
}
|
|
8143
|
+
}
|
|
8144
|
+
return currentGlobal[ValueProperties];
|
|
8145
|
+
}
|
|
8146
|
+
|
|
8147
|
+
class GlobalVariable extends Variable {
|
|
8148
|
+
constructor(name) {
|
|
8149
|
+
super(name);
|
|
8150
|
+
// Ensure we use live-bindings for globals as we do not know if they have
|
|
8151
|
+
// been reassigned
|
|
8152
|
+
this.markReassigned();
|
|
8153
|
+
}
|
|
8154
|
+
deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
|
|
8155
|
+
switch (interaction.type) {
|
|
8156
|
+
// While there is no point in testing these cases as at the moment, they
|
|
8157
|
+
// are also covered via other means, we keep them for completeness
|
|
8158
|
+
case INTERACTION_ACCESSED:
|
|
8159
|
+
case INTERACTION_ASSIGNED: {
|
|
8160
|
+
if (!getGlobalAtPath([this.name, ...path].slice(0, -1))) {
|
|
8161
|
+
super.deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker);
|
|
8162
|
+
}
|
|
8163
|
+
return;
|
|
8164
|
+
}
|
|
8165
|
+
case INTERACTION_CALLED: {
|
|
8166
|
+
const globalAtPath = getGlobalAtPath([this.name, ...path]);
|
|
8167
|
+
if (globalAtPath) {
|
|
8168
|
+
globalAtPath.deoptimizeArgumentsOnCall(interaction);
|
|
8169
|
+
}
|
|
8170
|
+
else {
|
|
8171
|
+
super.deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker);
|
|
8172
|
+
}
|
|
8173
|
+
return;
|
|
8174
|
+
}
|
|
8175
|
+
}
|
|
8176
|
+
}
|
|
8177
|
+
getLiteralValueAtPath(path, _recursionTracker, _origin) {
|
|
8178
|
+
const globalAtPath = getGlobalAtPath([this.name, ...path]);
|
|
8179
|
+
return globalAtPath ? globalAtPath.getLiteralValue() : UnknownValue;
|
|
8180
|
+
}
|
|
8181
|
+
hasEffectsOnInteractionAtPath(path, interaction, context) {
|
|
8182
|
+
switch (interaction.type) {
|
|
8183
|
+
case INTERACTION_ACCESSED: {
|
|
8184
|
+
if (path.length === 0) {
|
|
8185
|
+
// Technically, "undefined" is a global variable of sorts
|
|
8186
|
+
return this.name !== 'undefined' && !getGlobalAtPath([this.name]);
|
|
8187
|
+
}
|
|
8188
|
+
return !getGlobalAtPath([this.name, ...path].slice(0, -1));
|
|
8189
|
+
}
|
|
8190
|
+
case INTERACTION_ASSIGNED: {
|
|
8191
|
+
return true;
|
|
8192
|
+
}
|
|
8193
|
+
case INTERACTION_CALLED: {
|
|
8194
|
+
const globalAtPath = getGlobalAtPath([this.name, ...path]);
|
|
8195
|
+
return !globalAtPath || globalAtPath.hasEffectsWhenCalled(interaction, context);
|
|
8196
|
+
}
|
|
8197
|
+
}
|
|
8198
|
+
}
|
|
8199
|
+
}
|
|
8200
|
+
|
|
8201
|
+
class LocalVariable extends Variable {
|
|
8202
|
+
constructor(name, declarator, init, context, kind) {
|
|
8203
|
+
super(name);
|
|
8204
|
+
this.init = init;
|
|
8205
|
+
this.calledFromTryStatement = false;
|
|
8206
|
+
this.additionalInitializers = null;
|
|
8207
|
+
this.expressionsToBeDeoptimized = [];
|
|
8208
|
+
this.declarations = declarator ? [declarator] : [];
|
|
8209
|
+
this.deoptimizationTracker = context.deoptimizationTracker;
|
|
8210
|
+
this.module = context.module;
|
|
8211
|
+
this.kind = kind;
|
|
8212
|
+
}
|
|
8213
|
+
addDeclaration(identifier, init) {
|
|
8214
|
+
this.declarations.push(identifier);
|
|
8215
|
+
this.markInitializersForDeoptimization().push(init);
|
|
8216
|
+
}
|
|
8217
|
+
consolidateInitializers() {
|
|
8218
|
+
if (this.additionalInitializers) {
|
|
8219
|
+
for (const initializer of this.additionalInitializers) {
|
|
8220
|
+
initializer.deoptimizePath(UNKNOWN_PATH);
|
|
8221
|
+
}
|
|
8222
|
+
this.additionalInitializers = null;
|
|
8223
|
+
}
|
|
8224
|
+
}
|
|
8225
|
+
deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
|
|
8226
|
+
if (this.isReassigned) {
|
|
8227
|
+
deoptimizeInteraction(interaction);
|
|
8228
|
+
return;
|
|
8229
|
+
}
|
|
8230
|
+
recursionTracker.withTrackedEntityAtPath(path, this.init, () => this.init.deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker), undefined);
|
|
8231
|
+
}
|
|
8232
|
+
deoptimizePath(path) {
|
|
8233
|
+
if (this.isReassigned ||
|
|
8234
|
+
this.deoptimizationTracker.trackEntityAtPathAndGetIfTracked(path, this)) {
|
|
8235
|
+
return;
|
|
8236
|
+
}
|
|
8237
|
+
if (path.length === 0) {
|
|
8238
|
+
this.markReassigned();
|
|
8239
|
+
const expressionsToBeDeoptimized = this.expressionsToBeDeoptimized;
|
|
8240
|
+
this.expressionsToBeDeoptimized = parseAst_js.EMPTY_ARRAY;
|
|
8241
|
+
for (const expression of expressionsToBeDeoptimized) {
|
|
8242
|
+
expression.deoptimizeCache();
|
|
8243
|
+
}
|
|
8244
|
+
this.init.deoptimizePath(UNKNOWN_PATH);
|
|
8245
|
+
}
|
|
8246
|
+
else {
|
|
8247
|
+
this.init.deoptimizePath(path);
|
|
8248
|
+
}
|
|
8249
|
+
}
|
|
8250
|
+
getLiteralValueAtPath(path, recursionTracker, origin) {
|
|
8251
|
+
if (this.isReassigned) {
|
|
8252
|
+
return UnknownValue;
|
|
8253
|
+
}
|
|
8254
|
+
return recursionTracker.withTrackedEntityAtPath(path, this.init, () => {
|
|
8255
|
+
this.expressionsToBeDeoptimized.push(origin);
|
|
8256
|
+
return this.init.getLiteralValueAtPath(path, recursionTracker, origin);
|
|
8257
|
+
}, UnknownValue);
|
|
8258
|
+
}
|
|
8259
|
+
getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin) {
|
|
8260
|
+
if (this.isReassigned) {
|
|
8261
|
+
return UNKNOWN_RETURN_EXPRESSION;
|
|
8262
|
+
}
|
|
8263
|
+
return recursionTracker.withTrackedEntityAtPath(path, this.init, () => {
|
|
8264
|
+
this.expressionsToBeDeoptimized.push(origin);
|
|
8265
|
+
return this.init.getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin);
|
|
8266
|
+
}, UNKNOWN_RETURN_EXPRESSION);
|
|
8267
|
+
}
|
|
8268
|
+
hasEffectsOnInteractionAtPath(path, interaction, context) {
|
|
8269
|
+
switch (interaction.type) {
|
|
8270
|
+
case INTERACTION_ACCESSED: {
|
|
8271
|
+
if (this.isReassigned)
|
|
8272
|
+
return true;
|
|
8273
|
+
return (!context.accessed.trackEntityAtPathAndGetIfTracked(path, this) &&
|
|
8274
|
+
this.init.hasEffectsOnInteractionAtPath(path, interaction, context));
|
|
8275
|
+
}
|
|
8276
|
+
case INTERACTION_ASSIGNED: {
|
|
8277
|
+
if (this.included)
|
|
8278
|
+
return true;
|
|
8279
|
+
if (path.length === 0)
|
|
8280
|
+
return false;
|
|
8281
|
+
if (this.isReassigned)
|
|
8282
|
+
return true;
|
|
8283
|
+
return (!context.assigned.trackEntityAtPathAndGetIfTracked(path, this) &&
|
|
8284
|
+
this.init.hasEffectsOnInteractionAtPath(path, interaction, context));
|
|
8285
|
+
}
|
|
8286
|
+
case INTERACTION_CALLED: {
|
|
8287
|
+
if (this.isReassigned)
|
|
8288
|
+
return true;
|
|
8289
|
+
return (!(interaction.withNew ? context.instantiated : context.called).trackEntityAtPathAndGetIfTracked(path, interaction.args, this) &&
|
|
8290
|
+
this.init.hasEffectsOnInteractionAtPath(path, interaction, context));
|
|
8291
|
+
}
|
|
8292
|
+
}
|
|
8293
|
+
}
|
|
8294
|
+
include() {
|
|
8295
|
+
if (!this.included) {
|
|
8296
|
+
super.include();
|
|
8297
|
+
for (const declaration of this.declarations) {
|
|
8298
|
+
// If node is a default export, it can save a tree-shaking run to include the full declaration now
|
|
8299
|
+
if (!declaration.included)
|
|
8300
|
+
declaration.include(createInclusionContext(), false);
|
|
8301
|
+
let node = declaration.parent;
|
|
8302
|
+
while (!node.included) {
|
|
8303
|
+
// We do not want to properly include parents in case they are part of a dead branch
|
|
8304
|
+
// in which case .include() might pull in more dead code
|
|
8305
|
+
node.included = true;
|
|
8306
|
+
if (node.type === parseAst_js.Program)
|
|
8307
|
+
break;
|
|
8308
|
+
node = node.parent;
|
|
8309
|
+
}
|
|
8310
|
+
}
|
|
8311
|
+
}
|
|
8312
|
+
}
|
|
8313
|
+
includeCallArguments(context, parameters) {
|
|
8314
|
+
if (this.isReassigned || context.includedCallArguments.has(this.init)) {
|
|
8315
|
+
for (const argument of parameters) {
|
|
8316
|
+
argument.include(context, false);
|
|
8317
|
+
}
|
|
8318
|
+
}
|
|
8319
|
+
else {
|
|
8320
|
+
context.includedCallArguments.add(this.init);
|
|
8321
|
+
this.init.includeCallArguments(context, parameters);
|
|
8322
|
+
context.includedCallArguments.delete(this.init);
|
|
8323
|
+
}
|
|
8324
|
+
}
|
|
8325
|
+
markCalledFromTryStatement() {
|
|
8326
|
+
this.calledFromTryStatement = true;
|
|
8327
|
+
}
|
|
8328
|
+
markInitializersForDeoptimization() {
|
|
8329
|
+
if (this.additionalInitializers === null) {
|
|
8330
|
+
this.additionalInitializers = [this.init];
|
|
8331
|
+
this.init = UNKNOWN_EXPRESSION;
|
|
8332
|
+
this.markReassigned();
|
|
8333
|
+
}
|
|
8334
|
+
return this.additionalInitializers;
|
|
8335
|
+
}
|
|
8336
|
+
}
|
|
8337
|
+
|
|
8338
|
+
const tdzVariableKinds = new Set(['class', 'const', 'let', 'var', 'using', 'await using']);
|
|
8339
|
+
class Identifier extends NodeBase {
|
|
8340
|
+
constructor() {
|
|
8341
|
+
super(...arguments);
|
|
8342
|
+
this.variable = null;
|
|
8343
|
+
this.isReferenceVariable = false;
|
|
8344
|
+
}
|
|
8345
|
+
get isTDZAccess() {
|
|
8346
|
+
if (!isFlagSet(this.flags, 4 /* Flag.tdzAccessDefined */)) {
|
|
8666
8347
|
return null;
|
|
8667
8348
|
}
|
|
8668
|
-
|
|
8669
|
-
|
|
8670
|
-
|
|
8349
|
+
return isFlagSet(this.flags, 8 /* Flag.tdzAccess */);
|
|
8350
|
+
}
|
|
8351
|
+
set isTDZAccess(value) {
|
|
8352
|
+
this.flags = setFlag(this.flags, 4 /* Flag.tdzAccessDefined */, true);
|
|
8353
|
+
this.flags = setFlag(this.flags, 8 /* Flag.tdzAccess */, value);
|
|
8354
|
+
}
|
|
8355
|
+
addExportedVariables(variables, exportNamesByVariable) {
|
|
8356
|
+
if (exportNamesByVariable.has(this.variable)) {
|
|
8357
|
+
variables.push(this.variable);
|
|
8358
|
+
}
|
|
8359
|
+
}
|
|
8360
|
+
bind() {
|
|
8361
|
+
if (!this.variable && is_reference(this, this.parent)) {
|
|
8362
|
+
this.variable = this.scope.findVariable(this.name);
|
|
8363
|
+
this.variable.addReference(this);
|
|
8364
|
+
this.isReferenceVariable = true;
|
|
8365
|
+
}
|
|
8366
|
+
}
|
|
8367
|
+
declare(kind, init) {
|
|
8368
|
+
let variable;
|
|
8369
|
+
const { treeshake } = this.scope.context.options;
|
|
8370
|
+
switch (kind) {
|
|
8371
|
+
case 'var': {
|
|
8372
|
+
variable = this.scope.addDeclaration(this, this.scope.context, init, kind);
|
|
8373
|
+
if (treeshake && treeshake.correctVarValueBeforeDeclaration) {
|
|
8374
|
+
// Necessary to make sure the init is deoptimized. We cannot call deoptimizePath here.
|
|
8375
|
+
variable.markInitializersForDeoptimization();
|
|
8376
|
+
}
|
|
8377
|
+
break;
|
|
8378
|
+
}
|
|
8379
|
+
case 'function': {
|
|
8380
|
+
// in strict mode, functions are only hoisted within a scope but not across block scopes
|
|
8381
|
+
variable = this.scope.addDeclaration(this, this.scope.context, init, kind);
|
|
8382
|
+
break;
|
|
8383
|
+
}
|
|
8384
|
+
case 'let':
|
|
8385
|
+
case 'const':
|
|
8386
|
+
case 'using':
|
|
8387
|
+
case 'await using':
|
|
8388
|
+
case 'class': {
|
|
8389
|
+
variable = this.scope.addDeclaration(this, this.scope.context, init, kind);
|
|
8390
|
+
break;
|
|
8391
|
+
}
|
|
8392
|
+
case 'parameter': {
|
|
8393
|
+
variable = this.scope.addParameterDeclaration(this);
|
|
8394
|
+
break;
|
|
8395
|
+
}
|
|
8396
|
+
/* istanbul ignore next */
|
|
8397
|
+
default: {
|
|
8398
|
+
/* istanbul ignore next */
|
|
8399
|
+
throw new Error(`Internal Error: Unexpected identifier kind ${kind}.`);
|
|
8400
|
+
}
|
|
8401
|
+
}
|
|
8402
|
+
return [(this.variable = variable)];
|
|
8403
|
+
}
|
|
8404
|
+
deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
|
|
8405
|
+
this.variable.deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker);
|
|
8406
|
+
}
|
|
8407
|
+
deoptimizePath(path) {
|
|
8408
|
+
if (path.length === 0 && !this.scope.contains(this.name)) {
|
|
8409
|
+
this.disallowImportReassignment();
|
|
8410
|
+
}
|
|
8411
|
+
// We keep conditional chaining because an unknown Node could have an
|
|
8412
|
+
// Identifier as property that might be deoptimized by default
|
|
8413
|
+
this.variable?.deoptimizePath(path);
|
|
8414
|
+
}
|
|
8415
|
+
getLiteralValueAtPath(path, recursionTracker, origin) {
|
|
8416
|
+
return this.getVariableRespectingTDZ().getLiteralValueAtPath(path, recursionTracker, origin);
|
|
8417
|
+
}
|
|
8418
|
+
getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin) {
|
|
8419
|
+
const [expression, isPure] = this.getVariableRespectingTDZ().getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin);
|
|
8420
|
+
return [expression, isPure || this.isPureFunction(path)];
|
|
8421
|
+
}
|
|
8422
|
+
hasEffects(context) {
|
|
8423
|
+
if (!this.deoptimized)
|
|
8424
|
+
this.applyDeoptimizations();
|
|
8425
|
+
if (this.isPossibleTDZ() && this.variable.kind !== 'var') {
|
|
8426
|
+
return true;
|
|
8427
|
+
}
|
|
8428
|
+
return (this.scope.context.options.treeshake
|
|
8429
|
+
.unknownGlobalSideEffects &&
|
|
8430
|
+
this.variable instanceof GlobalVariable &&
|
|
8431
|
+
!this.isPureFunction(EMPTY_PATH) &&
|
|
8432
|
+
this.variable.hasEffectsOnInteractionAtPath(EMPTY_PATH, NODE_INTERACTION_UNKNOWN_ACCESS, context));
|
|
8433
|
+
}
|
|
8434
|
+
hasEffectsOnInteractionAtPath(path, interaction, context) {
|
|
8435
|
+
switch (interaction.type) {
|
|
8436
|
+
case INTERACTION_ACCESSED: {
|
|
8437
|
+
return (this.variable !== null &&
|
|
8438
|
+
!this.isPureFunction(path) &&
|
|
8439
|
+
this.getVariableRespectingTDZ().hasEffectsOnInteractionAtPath(path, interaction, context));
|
|
8440
|
+
}
|
|
8441
|
+
case INTERACTION_ASSIGNED: {
|
|
8442
|
+
return (path.length > 0 ? this.getVariableRespectingTDZ() : this.variable).hasEffectsOnInteractionAtPath(path, interaction, context);
|
|
8443
|
+
}
|
|
8444
|
+
case INTERACTION_CALLED: {
|
|
8445
|
+
return (!this.isPureFunction(path) &&
|
|
8446
|
+
this.getVariableRespectingTDZ().hasEffectsOnInteractionAtPath(path, interaction, context));
|
|
8447
|
+
}
|
|
8448
|
+
}
|
|
8449
|
+
}
|
|
8450
|
+
include() {
|
|
8451
|
+
if (!this.deoptimized)
|
|
8452
|
+
this.applyDeoptimizations();
|
|
8453
|
+
if (!this.included) {
|
|
8454
|
+
this.included = true;
|
|
8455
|
+
if (this.variable !== null) {
|
|
8456
|
+
this.scope.context.includeVariableInModule(this.variable);
|
|
8457
|
+
}
|
|
8458
|
+
}
|
|
8459
|
+
}
|
|
8460
|
+
includeCallArguments(context, parameters) {
|
|
8461
|
+
this.variable.includeCallArguments(context, parameters);
|
|
8462
|
+
}
|
|
8463
|
+
isPossibleTDZ() {
|
|
8464
|
+
// return cached value to avoid issues with the next tree-shaking pass
|
|
8465
|
+
const cachedTdzAccess = this.isTDZAccess;
|
|
8466
|
+
if (cachedTdzAccess !== null)
|
|
8467
|
+
return cachedTdzAccess;
|
|
8468
|
+
if (!(this.variable instanceof LocalVariable &&
|
|
8469
|
+
this.variable.kind &&
|
|
8470
|
+
tdzVariableKinds.has(this.variable.kind) &&
|
|
8471
|
+
// we ignore possible TDZs due to circular module dependencies as
|
|
8472
|
+
// otherwise we get many false positives
|
|
8473
|
+
this.variable.module === this.scope.context.module)) {
|
|
8474
|
+
return (this.isTDZAccess = false);
|
|
8475
|
+
}
|
|
8476
|
+
let decl_id;
|
|
8477
|
+
if (this.variable.declarations &&
|
|
8478
|
+
this.variable.declarations.length === 1 &&
|
|
8479
|
+
(decl_id = this.variable.declarations[0]) &&
|
|
8480
|
+
this.start < decl_id.start &&
|
|
8481
|
+
closestParentFunctionOrProgram(this) === closestParentFunctionOrProgram(decl_id)) {
|
|
8482
|
+
// a variable accessed before its declaration
|
|
8483
|
+
// in the same function or at top level of module
|
|
8484
|
+
return (this.isTDZAccess = true);
|
|
8485
|
+
}
|
|
8486
|
+
// We ignore the case where the module is not yet executed because
|
|
8487
|
+
// moduleSideEffects are false.
|
|
8488
|
+
if (!this.variable.initReached && this.scope.context.module.isExecuted) {
|
|
8489
|
+
// Either a const/let TDZ violation or
|
|
8490
|
+
// var use before declaration was encountered.
|
|
8491
|
+
return (this.isTDZAccess = true);
|
|
8671
8492
|
}
|
|
8493
|
+
return (this.isTDZAccess = false);
|
|
8672
8494
|
}
|
|
8673
|
-
|
|
8674
|
-
|
|
8675
|
-
|
|
8676
|
-
class GlobalVariable extends Variable {
|
|
8677
|
-
constructor() {
|
|
8678
|
-
super(...arguments);
|
|
8679
|
-
// Ensure we use live-bindings for globals as we do not know if they have
|
|
8680
|
-
// been reassigned
|
|
8681
|
-
this.isReassigned = true;
|
|
8495
|
+
markDeclarationReached() {
|
|
8496
|
+
this.variable.initReached = true;
|
|
8682
8497
|
}
|
|
8683
|
-
|
|
8684
|
-
|
|
8685
|
-
|
|
8686
|
-
|
|
8687
|
-
|
|
8688
|
-
|
|
8689
|
-
|
|
8690
|
-
|
|
8498
|
+
render(code, { snippets: { getPropertyAccess }, useOriginalName }, { renderedParentType, isCalleeOfRenderedParent, isShorthandProperty } = parseAst_js.BLANK) {
|
|
8499
|
+
if (this.variable) {
|
|
8500
|
+
const name = this.variable.getName(getPropertyAccess, useOriginalName);
|
|
8501
|
+
if (name !== this.name) {
|
|
8502
|
+
code.overwrite(this.start, this.end, name, {
|
|
8503
|
+
contentOnly: true,
|
|
8504
|
+
storeName: true
|
|
8505
|
+
});
|
|
8506
|
+
if (isShorthandProperty) {
|
|
8507
|
+
code.prependRight(this.start, `${this.name}: `);
|
|
8691
8508
|
}
|
|
8692
|
-
return;
|
|
8693
8509
|
}
|
|
8694
|
-
|
|
8695
|
-
|
|
8696
|
-
|
|
8697
|
-
|
|
8510
|
+
// In strict mode, any variable named "eval" must be the actual "eval" function
|
|
8511
|
+
if (name === 'eval' &&
|
|
8512
|
+
renderedParentType === parseAst_js.CallExpression &&
|
|
8513
|
+
isCalleeOfRenderedParent) {
|
|
8514
|
+
code.appendRight(this.start, '0, ');
|
|
8515
|
+
}
|
|
8516
|
+
}
|
|
8517
|
+
}
|
|
8518
|
+
disallowImportReassignment() {
|
|
8519
|
+
return this.scope.context.error(parseAst_js.logIllegalImportReassignment(this.name, this.scope.context.module.id), this.start);
|
|
8520
|
+
}
|
|
8521
|
+
applyDeoptimizations() {
|
|
8522
|
+
this.deoptimized = true;
|
|
8523
|
+
if (this.variable instanceof LocalVariable) {
|
|
8524
|
+
this.variable.consolidateInitializers();
|
|
8525
|
+
this.scope.context.requestTreeshakingPass();
|
|
8526
|
+
}
|
|
8527
|
+
if (this.isReferenceVariable) {
|
|
8528
|
+
this.variable.addUsedPlace(this);
|
|
8529
|
+
this.scope.context.requestTreeshakingPass();
|
|
8530
|
+
}
|
|
8531
|
+
}
|
|
8532
|
+
getVariableRespectingTDZ() {
|
|
8533
|
+
if (this.isPossibleTDZ()) {
|
|
8534
|
+
return UNKNOWN_EXPRESSION;
|
|
8535
|
+
}
|
|
8536
|
+
return this.variable;
|
|
8537
|
+
}
|
|
8538
|
+
isPureFunction(path) {
|
|
8539
|
+
let currentPureFunction = this.scope.context.manualPureFunctions[this.name];
|
|
8540
|
+
for (const segment of path) {
|
|
8541
|
+
if (currentPureFunction) {
|
|
8542
|
+
if (currentPureFunction[PureFunctionKey]) {
|
|
8543
|
+
return true;
|
|
8698
8544
|
}
|
|
8699
|
-
|
|
8700
|
-
|
|
8545
|
+
currentPureFunction = currentPureFunction[segment];
|
|
8546
|
+
}
|
|
8547
|
+
else {
|
|
8548
|
+
return false;
|
|
8549
|
+
}
|
|
8550
|
+
}
|
|
8551
|
+
return currentPureFunction?.[PureFunctionKey];
|
|
8552
|
+
}
|
|
8553
|
+
}
|
|
8554
|
+
function closestParentFunctionOrProgram(node) {
|
|
8555
|
+
while (node && !/^Program|Function/.test(node.type)) {
|
|
8556
|
+
node = node.parent;
|
|
8557
|
+
}
|
|
8558
|
+
// one of: ArrowFunctionExpression, FunctionDeclaration, FunctionExpression or Program
|
|
8559
|
+
return node;
|
|
8560
|
+
}
|
|
8561
|
+
|
|
8562
|
+
const MAX_TRACKED_INTERACTIONS = 20;
|
|
8563
|
+
const NO_INTERACTIONS = parseAst_js.EMPTY_ARRAY;
|
|
8564
|
+
const UNKNOWN_DEOPTIMIZED_FIELD = new Set([UnknownKey]);
|
|
8565
|
+
const EMPTY_PATH_TRACKER = new PathTracker();
|
|
8566
|
+
const UNKNOWN_DEOPTIMIZED_ENTITY = new Set([UNKNOWN_EXPRESSION]);
|
|
8567
|
+
class ParameterVariable extends LocalVariable {
|
|
8568
|
+
constructor(name, declarator, context) {
|
|
8569
|
+
super(name, declarator, UNKNOWN_EXPRESSION, context, 'parameter');
|
|
8570
|
+
this.deoptimizationInteractions = [];
|
|
8571
|
+
this.deoptimizations = new PathTracker();
|
|
8572
|
+
this.deoptimizedFields = new Set();
|
|
8573
|
+
this.entitiesToBeDeoptimized = new Set();
|
|
8574
|
+
this.expressionsUseTheKnownValue = [];
|
|
8575
|
+
this.knownValue = null;
|
|
8576
|
+
this.knownValueLiteral = UnknownValue;
|
|
8577
|
+
this.frozenValue = null;
|
|
8578
|
+
}
|
|
8579
|
+
addEntityToBeDeoptimized(entity) {
|
|
8580
|
+
if (entity === UNKNOWN_EXPRESSION) {
|
|
8581
|
+
// As unknown expressions fully deoptimize all interactions, we can clear
|
|
8582
|
+
// the interaction cache at this point provided we keep this optimization
|
|
8583
|
+
// in mind when adding new interactions
|
|
8584
|
+
if (!this.entitiesToBeDeoptimized.has(UNKNOWN_EXPRESSION)) {
|
|
8585
|
+
this.entitiesToBeDeoptimized.add(UNKNOWN_EXPRESSION);
|
|
8586
|
+
for (const { interaction } of this.deoptimizationInteractions) {
|
|
8587
|
+
deoptimizeInteraction(interaction);
|
|
8701
8588
|
}
|
|
8702
|
-
|
|
8589
|
+
this.deoptimizationInteractions = NO_INTERACTIONS;
|
|
8590
|
+
}
|
|
8591
|
+
}
|
|
8592
|
+
else if (this.deoptimizedFields.has(UnknownKey)) {
|
|
8593
|
+
// This means that we already deoptimized all interactions and no longer
|
|
8594
|
+
// track them
|
|
8595
|
+
entity.deoptimizePath(UNKNOWN_PATH);
|
|
8596
|
+
}
|
|
8597
|
+
else if (!this.entitiesToBeDeoptimized.has(entity)) {
|
|
8598
|
+
this.entitiesToBeDeoptimized.add(entity);
|
|
8599
|
+
for (const field of this.deoptimizedFields) {
|
|
8600
|
+
entity.deoptimizePath([field]);
|
|
8601
|
+
}
|
|
8602
|
+
for (const { interaction, path } of this.deoptimizationInteractions) {
|
|
8603
|
+
entity.deoptimizeArgumentsOnInteractionAtPath(interaction, path, SHARED_RECURSION_TRACKER);
|
|
8604
|
+
}
|
|
8605
|
+
}
|
|
8606
|
+
}
|
|
8607
|
+
markReassigned() {
|
|
8608
|
+
if (this.isReassigned) {
|
|
8609
|
+
return;
|
|
8610
|
+
}
|
|
8611
|
+
super.markReassigned();
|
|
8612
|
+
for (const expression of this.expressionsUseTheKnownValue) {
|
|
8613
|
+
expression.deoptimizeCache();
|
|
8614
|
+
}
|
|
8615
|
+
this.expressionsUseTheKnownValue = parseAst_js.EMPTY_ARRAY;
|
|
8616
|
+
}
|
|
8617
|
+
deoptimizeCache() {
|
|
8618
|
+
this.markReassigned();
|
|
8619
|
+
}
|
|
8620
|
+
/**
|
|
8621
|
+
* Update the known value of the parameter variable.
|
|
8622
|
+
* Must be called for every function call, so it can track all the arguments,
|
|
8623
|
+
* and deoptimizeCache itself to mark reassigned if the argument is changed.
|
|
8624
|
+
* @param argument The argument of the function call
|
|
8625
|
+
*/
|
|
8626
|
+
updateKnownValue(argument) {
|
|
8627
|
+
if (this.isReassigned) {
|
|
8628
|
+
return;
|
|
8629
|
+
}
|
|
8630
|
+
if (this.knownValue === null) {
|
|
8631
|
+
this.knownValue = argument;
|
|
8632
|
+
this.knownValueLiteral = argument.getLiteralValueAtPath(EMPTY_PATH, SHARED_RECURSION_TRACKER, this);
|
|
8633
|
+
return;
|
|
8634
|
+
}
|
|
8635
|
+
// the same literal or identifier, do nothing
|
|
8636
|
+
if (this.knownValue === argument ||
|
|
8637
|
+
(this.knownValue instanceof Identifier &&
|
|
8638
|
+
argument instanceof Identifier &&
|
|
8639
|
+
this.knownValue.variable === argument.variable)) {
|
|
8640
|
+
return;
|
|
8641
|
+
}
|
|
8642
|
+
const oldValue = this.knownValueLiteral;
|
|
8643
|
+
if (typeof oldValue === 'symbol') {
|
|
8644
|
+
this.markReassigned();
|
|
8645
|
+
return;
|
|
8646
|
+
}
|
|
8647
|
+
// add tracking for the new argument
|
|
8648
|
+
const newValue = argument.getLiteralValueAtPath(EMPTY_PATH, SHARED_RECURSION_TRACKER, this);
|
|
8649
|
+
if (newValue !== oldValue) {
|
|
8650
|
+
this.markReassigned();
|
|
8651
|
+
}
|
|
8652
|
+
}
|
|
8653
|
+
/**
|
|
8654
|
+
* This function freezes the known value of the parameter variable,
|
|
8655
|
+
* so the optimization starts with a certain ExpressionEntity.
|
|
8656
|
+
* The optimization can be undone by calling `markReassigned`.
|
|
8657
|
+
* @returns the frozen value
|
|
8658
|
+
*/
|
|
8659
|
+
getKnownValue() {
|
|
8660
|
+
if (this.frozenValue === null) {
|
|
8661
|
+
this.frozenValue = this.knownValue || UNKNOWN_EXPRESSION;
|
|
8662
|
+
}
|
|
8663
|
+
return this.frozenValue;
|
|
8664
|
+
}
|
|
8665
|
+
getLiteralValueAtPath(path, recursionTracker, origin) {
|
|
8666
|
+
if (this.isReassigned) {
|
|
8667
|
+
return UnknownValue;
|
|
8668
|
+
}
|
|
8669
|
+
const knownValue = this.getKnownValue();
|
|
8670
|
+
this.expressionsUseTheKnownValue.push(origin);
|
|
8671
|
+
return recursionTracker.withTrackedEntityAtPath(path, knownValue, () => knownValue.getLiteralValueAtPath(path, recursionTracker, origin), UnknownValue);
|
|
8672
|
+
}
|
|
8673
|
+
hasEffectsOnInteractionAtPath(path, interaction, context) {
|
|
8674
|
+
if (this.isReassigned || interaction.type === INTERACTION_ASSIGNED) {
|
|
8675
|
+
return super.hasEffectsOnInteractionAtPath(path, interaction, context);
|
|
8676
|
+
}
|
|
8677
|
+
const knownValue = this.getKnownValue();
|
|
8678
|
+
return knownValue.hasEffectsOnInteractionAtPath(path, interaction, context);
|
|
8679
|
+
}
|
|
8680
|
+
deoptimizeArgumentsOnInteractionAtPath(interaction, path) {
|
|
8681
|
+
// For performance reasons, we fully deoptimize all deeper interactions
|
|
8682
|
+
if (path.length >= 2 ||
|
|
8683
|
+
this.entitiesToBeDeoptimized.has(UNKNOWN_EXPRESSION) ||
|
|
8684
|
+
this.deoptimizationInteractions.length >= MAX_TRACKED_INTERACTIONS ||
|
|
8685
|
+
(path.length === 1 &&
|
|
8686
|
+
(this.deoptimizedFields.has(UnknownKey) ||
|
|
8687
|
+
(interaction.type === INTERACTION_CALLED && this.deoptimizedFields.has(path[0]))))) {
|
|
8688
|
+
deoptimizeInteraction(interaction);
|
|
8689
|
+
return;
|
|
8690
|
+
}
|
|
8691
|
+
if (!this.deoptimizations.trackEntityAtPathAndGetIfTracked(path, interaction.args)) {
|
|
8692
|
+
for (const entity of this.entitiesToBeDeoptimized) {
|
|
8693
|
+
entity.deoptimizeArgumentsOnInteractionAtPath(interaction, path, SHARED_RECURSION_TRACKER);
|
|
8703
8694
|
}
|
|
8695
|
+
if (!this.entitiesToBeDeoptimized.has(UNKNOWN_EXPRESSION)) {
|
|
8696
|
+
this.deoptimizationInteractions.push({
|
|
8697
|
+
interaction,
|
|
8698
|
+
path
|
|
8699
|
+
});
|
|
8700
|
+
}
|
|
8701
|
+
}
|
|
8702
|
+
}
|
|
8703
|
+
deoptimizePath(path) {
|
|
8704
|
+
if (path.length === 0) {
|
|
8705
|
+
this.markReassigned();
|
|
8706
|
+
return;
|
|
8707
|
+
}
|
|
8708
|
+
if (this.deoptimizedFields.has(UnknownKey)) {
|
|
8709
|
+
return;
|
|
8710
|
+
}
|
|
8711
|
+
const key = path[0];
|
|
8712
|
+
if (this.deoptimizedFields.has(key)) {
|
|
8713
|
+
return;
|
|
8714
|
+
}
|
|
8715
|
+
this.deoptimizedFields.add(key);
|
|
8716
|
+
for (const entity of this.entitiesToBeDeoptimized) {
|
|
8717
|
+
// We do not need a recursion tracker here as we already track whether
|
|
8718
|
+
// this field is deoptimized
|
|
8719
|
+
entity.deoptimizePath([key]);
|
|
8720
|
+
}
|
|
8721
|
+
if (key === UnknownKey) {
|
|
8722
|
+
// save some memory
|
|
8723
|
+
this.deoptimizationInteractions = NO_INTERACTIONS;
|
|
8724
|
+
this.deoptimizations = EMPTY_PATH_TRACKER;
|
|
8725
|
+
this.deoptimizedFields = UNKNOWN_DEOPTIMIZED_FIELD;
|
|
8726
|
+
this.entitiesToBeDeoptimized = UNKNOWN_DEOPTIMIZED_ENTITY;
|
|
8727
|
+
}
|
|
8728
|
+
}
|
|
8729
|
+
getReturnExpressionWhenCalledAtPath(path) {
|
|
8730
|
+
// We deoptimize everything that is called as that will trivially deoptimize
|
|
8731
|
+
// the corresponding return expressions as well and avoid badly performing
|
|
8732
|
+
// and complicated alternatives
|
|
8733
|
+
if (path.length === 0) {
|
|
8734
|
+
this.deoptimizePath(UNKNOWN_PATH);
|
|
8735
|
+
}
|
|
8736
|
+
else if (!this.deoptimizedFields.has(path[0])) {
|
|
8737
|
+
this.deoptimizePath([path[0]]);
|
|
8704
8738
|
}
|
|
8739
|
+
return UNKNOWN_RETURN_EXPRESSION;
|
|
8705
8740
|
}
|
|
8706
|
-
|
|
8707
|
-
|
|
8708
|
-
|
|
8709
|
-
|
|
8710
|
-
|
|
8711
|
-
|
|
8712
|
-
|
|
8713
|
-
if (path.length === 0) {
|
|
8714
|
-
// Technically, "undefined" is a global variable of sorts
|
|
8715
|
-
return this.name !== 'undefined' && !getGlobalAtPath([this.name]);
|
|
8716
|
-
}
|
|
8717
|
-
return !getGlobalAtPath([this.name, ...path].slice(0, -1));
|
|
8718
|
-
}
|
|
8719
|
-
case INTERACTION_ASSIGNED: {
|
|
8720
|
-
return true;
|
|
8721
|
-
}
|
|
8722
|
-
case INTERACTION_CALLED: {
|
|
8723
|
-
const globalAtPath = getGlobalAtPath([this.name, ...path]);
|
|
8724
|
-
return !globalAtPath || globalAtPath.hasEffectsWhenCalled(interaction, context);
|
|
8725
|
-
}
|
|
8726
|
-
}
|
|
8741
|
+
}
|
|
8742
|
+
|
|
8743
|
+
function getSafeName(baseName, usedNames, forbiddenNames) {
|
|
8744
|
+
let safeName = baseName;
|
|
8745
|
+
let count = 1;
|
|
8746
|
+
while (usedNames.has(safeName) || RESERVED_NAMES.has(safeName) || forbiddenNames?.has(safeName)) {
|
|
8747
|
+
safeName = `${baseName}$${toBase64(count++)}`;
|
|
8727
8748
|
}
|
|
8749
|
+
usedNames.add(safeName);
|
|
8750
|
+
return safeName;
|
|
8728
8751
|
}
|
|
8729
8752
|
|
|
8730
|
-
|
|
8731
|
-
class Identifier extends NodeBase {
|
|
8753
|
+
class Scope {
|
|
8732
8754
|
constructor() {
|
|
8733
|
-
|
|
8734
|
-
this.
|
|
8755
|
+
this.children = [];
|
|
8756
|
+
this.variables = new Map();
|
|
8735
8757
|
}
|
|
8736
|
-
|
|
8737
|
-
|
|
8738
|
-
|
|
8758
|
+
/*
|
|
8759
|
+
Redeclaration rules:
|
|
8760
|
+
- var can redeclare var
|
|
8761
|
+
- in function scopes, function and var can redeclare function and var
|
|
8762
|
+
- var is hoisted across scopes, function remains in the scope it is declared
|
|
8763
|
+
- var and function can redeclare function parameters, but parameters cannot redeclare parameters
|
|
8764
|
+
- function cannot redeclare catch scope parameters
|
|
8765
|
+
- var can redeclare catch scope parameters in a way
|
|
8766
|
+
- if the parameter is an identifier and not a pattern
|
|
8767
|
+
- then the variable is still declared in the hoisted outer scope, but the initializer is assigned to the parameter
|
|
8768
|
+
- const, let, class, and function except in the cases above cannot redeclare anything
|
|
8769
|
+
*/
|
|
8770
|
+
addDeclaration(identifier, context, init, kind) {
|
|
8771
|
+
const name = identifier.name;
|
|
8772
|
+
const existingVariable = this.hoistedVariables?.get(name) || this.variables.get(name);
|
|
8773
|
+
if (existingVariable) {
|
|
8774
|
+
const existingKind = existingVariable.kind;
|
|
8775
|
+
if (kind === 'var' && existingKind === 'var') {
|
|
8776
|
+
existingVariable.addDeclaration(identifier, init);
|
|
8777
|
+
return existingVariable;
|
|
8778
|
+
}
|
|
8779
|
+
context.error(parseAst_js.logRedeclarationError(name), identifier.start);
|
|
8739
8780
|
}
|
|
8740
|
-
|
|
8781
|
+
const newVariable = new LocalVariable(identifier.name, identifier, init, context, kind);
|
|
8782
|
+
this.variables.set(name, newVariable);
|
|
8783
|
+
return newVariable;
|
|
8741
8784
|
}
|
|
8742
|
-
|
|
8743
|
-
this.
|
|
8744
|
-
this.flags = setFlag(this.flags, 8 /* Flag.tdzAccess */, value);
|
|
8785
|
+
addHoistedVariable(name, variable) {
|
|
8786
|
+
(this.hoistedVariables ||= new Map()).set(name, variable);
|
|
8745
8787
|
}
|
|
8746
|
-
|
|
8747
|
-
|
|
8748
|
-
|
|
8788
|
+
contains(name) {
|
|
8789
|
+
return this.variables.has(name);
|
|
8790
|
+
}
|
|
8791
|
+
findVariable(_name) {
|
|
8792
|
+
/* istanbul ignore next */
|
|
8793
|
+
throw new Error('Internal Error: findVariable needs to be implemented by a subclass');
|
|
8794
|
+
}
|
|
8795
|
+
}
|
|
8796
|
+
|
|
8797
|
+
class ChildScope extends Scope {
|
|
8798
|
+
constructor(parent, context) {
|
|
8799
|
+
super();
|
|
8800
|
+
this.parent = parent;
|
|
8801
|
+
this.context = context;
|
|
8802
|
+
this.accessedOutsideVariables = new Map();
|
|
8803
|
+
parent.children.push(this);
|
|
8804
|
+
}
|
|
8805
|
+
addAccessedDynamicImport(importExpression) {
|
|
8806
|
+
(this.accessedDynamicImports || (this.accessedDynamicImports = new Set())).add(importExpression);
|
|
8807
|
+
if (this.parent instanceof ChildScope) {
|
|
8808
|
+
this.parent.addAccessedDynamicImport(importExpression);
|
|
8749
8809
|
}
|
|
8750
8810
|
}
|
|
8751
|
-
|
|
8752
|
-
|
|
8753
|
-
|
|
8754
|
-
|
|
8811
|
+
addAccessedGlobals(globals, accessedGlobalsByScope) {
|
|
8812
|
+
const accessedGlobals = accessedGlobalsByScope.get(this) || new Set();
|
|
8813
|
+
for (const name of globals) {
|
|
8814
|
+
accessedGlobals.add(name);
|
|
8815
|
+
}
|
|
8816
|
+
accessedGlobalsByScope.set(this, accessedGlobals);
|
|
8817
|
+
if (this.parent instanceof ChildScope) {
|
|
8818
|
+
this.parent.addAccessedGlobals(globals, accessedGlobalsByScope);
|
|
8755
8819
|
}
|
|
8756
8820
|
}
|
|
8757
|
-
|
|
8758
|
-
|
|
8759
|
-
|
|
8760
|
-
|
|
8761
|
-
|
|
8762
|
-
|
|
8763
|
-
|
|
8764
|
-
|
|
8765
|
-
|
|
8821
|
+
addNamespaceMemberAccess(name, variable) {
|
|
8822
|
+
this.accessedOutsideVariables.set(name, variable);
|
|
8823
|
+
this.parent.addNamespaceMemberAccess(name, variable);
|
|
8824
|
+
}
|
|
8825
|
+
addReturnExpression(expression) {
|
|
8826
|
+
this.parent instanceof ChildScope && this.parent.addReturnExpression(expression);
|
|
8827
|
+
}
|
|
8828
|
+
addUsedOutsideNames(usedNames, format, exportNamesByVariable, accessedGlobalsByScope) {
|
|
8829
|
+
for (const variable of this.accessedOutsideVariables.values()) {
|
|
8830
|
+
if (variable.included) {
|
|
8831
|
+
usedNames.add(variable.getBaseVariableName());
|
|
8832
|
+
if (format === 'system' && exportNamesByVariable.has(variable)) {
|
|
8833
|
+
usedNames.add('exports');
|
|
8766
8834
|
}
|
|
8767
|
-
break;
|
|
8768
|
-
}
|
|
8769
|
-
case 'function': {
|
|
8770
|
-
// in strict mode, functions are only hoisted within a scope but not across block scopes
|
|
8771
|
-
variable = this.scope.addDeclaration(this, this.scope.context, init, kind);
|
|
8772
|
-
break;
|
|
8773
|
-
}
|
|
8774
|
-
case 'let':
|
|
8775
|
-
case 'const':
|
|
8776
|
-
case 'using':
|
|
8777
|
-
case 'await using':
|
|
8778
|
-
case 'class': {
|
|
8779
|
-
variable = this.scope.addDeclaration(this, this.scope.context, init, kind);
|
|
8780
|
-
break;
|
|
8781
|
-
}
|
|
8782
|
-
case 'parameter': {
|
|
8783
|
-
variable = this.scope.addParameterDeclaration(this);
|
|
8784
|
-
break;
|
|
8785
8835
|
}
|
|
8786
|
-
|
|
8787
|
-
|
|
8788
|
-
|
|
8789
|
-
|
|
8836
|
+
}
|
|
8837
|
+
const accessedGlobals = accessedGlobalsByScope.get(this);
|
|
8838
|
+
if (accessedGlobals) {
|
|
8839
|
+
for (const name of accessedGlobals) {
|
|
8840
|
+
usedNames.add(name);
|
|
8790
8841
|
}
|
|
8791
8842
|
}
|
|
8792
|
-
return [(this.variable = variable)];
|
|
8793
8843
|
}
|
|
8794
|
-
|
|
8795
|
-
this.
|
|
8844
|
+
contains(name) {
|
|
8845
|
+
return this.variables.has(name) || this.parent.contains(name);
|
|
8796
8846
|
}
|
|
8797
|
-
|
|
8798
|
-
|
|
8799
|
-
|
|
8847
|
+
deconflict(format, exportNamesByVariable, accessedGlobalsByScope) {
|
|
8848
|
+
const usedNames = new Set();
|
|
8849
|
+
this.addUsedOutsideNames(usedNames, format, exportNamesByVariable, accessedGlobalsByScope);
|
|
8850
|
+
if (this.accessedDynamicImports) {
|
|
8851
|
+
for (const importExpression of this.accessedDynamicImports) {
|
|
8852
|
+
if (importExpression.inlineNamespace) {
|
|
8853
|
+
usedNames.add(importExpression.inlineNamespace.getBaseVariableName());
|
|
8854
|
+
}
|
|
8855
|
+
}
|
|
8856
|
+
}
|
|
8857
|
+
for (const [name, variable] of this.variables) {
|
|
8858
|
+
if (variable.included || variable.alwaysRendered) {
|
|
8859
|
+
variable.setRenderNames(null, getSafeName(name, usedNames, variable.forbiddenNames));
|
|
8860
|
+
}
|
|
8861
|
+
}
|
|
8862
|
+
for (const scope of this.children) {
|
|
8863
|
+
scope.deconflict(format, exportNamesByVariable, accessedGlobalsByScope);
|
|
8800
8864
|
}
|
|
8801
|
-
// We keep conditional chaining because an unknown Node could have an
|
|
8802
|
-
// Identifier as property that might be deoptimized by default
|
|
8803
|
-
this.variable?.deoptimizePath(path);
|
|
8804
|
-
}
|
|
8805
|
-
getLiteralValueAtPath(path, recursionTracker, origin) {
|
|
8806
|
-
return this.getVariableRespectingTDZ().getLiteralValueAtPath(path, recursionTracker, origin);
|
|
8807
8865
|
}
|
|
8808
|
-
|
|
8809
|
-
|
|
8810
|
-
return [expression, isPure || this.isPureFunction(path)];
|
|
8866
|
+
findLexicalBoundary() {
|
|
8867
|
+
return this.parent.findLexicalBoundary();
|
|
8811
8868
|
}
|
|
8812
|
-
|
|
8813
|
-
|
|
8814
|
-
|
|
8815
|
-
|
|
8816
|
-
return true;
|
|
8869
|
+
findVariable(name) {
|
|
8870
|
+
const knownVariable = this.variables.get(name) || this.accessedOutsideVariables.get(name);
|
|
8871
|
+
if (knownVariable) {
|
|
8872
|
+
return knownVariable;
|
|
8817
8873
|
}
|
|
8818
|
-
|
|
8819
|
-
|
|
8820
|
-
|
|
8821
|
-
!this.isPureFunction(EMPTY_PATH) &&
|
|
8822
|
-
this.variable.hasEffectsOnInteractionAtPath(EMPTY_PATH, NODE_INTERACTION_UNKNOWN_ACCESS, context));
|
|
8874
|
+
const variable = this.parent.findVariable(name);
|
|
8875
|
+
this.accessedOutsideVariables.set(name, variable);
|
|
8876
|
+
return variable;
|
|
8823
8877
|
}
|
|
8824
|
-
|
|
8825
|
-
|
|
8826
|
-
|
|
8827
|
-
|
|
8828
|
-
|
|
8829
|
-
|
|
8830
|
-
|
|
8831
|
-
|
|
8832
|
-
|
|
8833
|
-
|
|
8834
|
-
|
|
8835
|
-
|
|
8836
|
-
|
|
8878
|
+
}
|
|
8879
|
+
|
|
8880
|
+
class CatchBodyScope extends ChildScope {
|
|
8881
|
+
constructor(parent) {
|
|
8882
|
+
super(parent, parent.context);
|
|
8883
|
+
this.parent = parent;
|
|
8884
|
+
}
|
|
8885
|
+
addDeclaration(identifier, context, init, kind) {
|
|
8886
|
+
if (kind === 'var') {
|
|
8887
|
+
const name = identifier.name;
|
|
8888
|
+
const existingVariable = this.hoistedVariables?.get(name) || this.variables.get(name);
|
|
8889
|
+
if (existingVariable) {
|
|
8890
|
+
const existingKind = existingVariable.kind;
|
|
8891
|
+
if (existingKind === 'parameter' &&
|
|
8892
|
+
// If this is a destructured parameter, it is forbidden to redeclare
|
|
8893
|
+
existingVariable.declarations[0].parent.type === parseAst_js.CatchClause) {
|
|
8894
|
+
// If this is a var with the same name as the catch scope parameter,
|
|
8895
|
+
// the assignment actually goes to the parameter and the var is
|
|
8896
|
+
// hoisted without assignment. Locally, it is shadowed by the
|
|
8897
|
+
// parameter
|
|
8898
|
+
const declaredVariable = this.parent.parent.addDeclaration(identifier, context, UNDEFINED_EXPRESSION, kind);
|
|
8899
|
+
// To avoid the need to rewrite the declaration, we link the variable
|
|
8900
|
+
// names. If we ever implement a logic that splits initialization and
|
|
8901
|
+
// assignment for hoisted vars, the "renderLikeHoisted" logic can be
|
|
8902
|
+
// removed again.
|
|
8903
|
+
// We do not need to check whether there already is a linked
|
|
8904
|
+
// variable because then declaredVariable would be that linked
|
|
8905
|
+
// variable.
|
|
8906
|
+
existingVariable.renderLikeHoisted(declaredVariable);
|
|
8907
|
+
this.addHoistedVariable(name, declaredVariable);
|
|
8908
|
+
return declaredVariable;
|
|
8909
|
+
}
|
|
8910
|
+
if (existingKind === 'var') {
|
|
8911
|
+
existingVariable.addDeclaration(identifier, init);
|
|
8912
|
+
return existingVariable;
|
|
8913
|
+
}
|
|
8914
|
+
return context.error(parseAst_js.logRedeclarationError(name), identifier.start);
|
|
8837
8915
|
}
|
|
8916
|
+
// We only add parameters to parameter scopes
|
|
8917
|
+
const declaredVariable = this.parent.parent.addDeclaration(identifier, context, init, kind);
|
|
8918
|
+
// Necessary to make sure the init is deoptimized for conditional declarations.
|
|
8919
|
+
// We cannot call deoptimizePath here.
|
|
8920
|
+
declaredVariable.markInitializersForDeoptimization();
|
|
8921
|
+
// We add the variable to this and all parent scopes to reliably detect conflicts
|
|
8922
|
+
this.addHoistedVariable(name, declaredVariable);
|
|
8923
|
+
return declaredVariable;
|
|
8838
8924
|
}
|
|
8925
|
+
return super.addDeclaration(identifier, context, init, kind);
|
|
8839
8926
|
}
|
|
8840
|
-
|
|
8841
|
-
|
|
8842
|
-
|
|
8843
|
-
|
|
8844
|
-
|
|
8845
|
-
|
|
8846
|
-
|
|
8927
|
+
}
|
|
8928
|
+
|
|
8929
|
+
class FunctionBodyScope extends ChildScope {
|
|
8930
|
+
constructor(parent) {
|
|
8931
|
+
super(parent, parent.context);
|
|
8932
|
+
}
|
|
8933
|
+
// There is stuff that is only allowed in function scopes, i.e. functions can
|
|
8934
|
+
// be redeclared, functions and var can redeclare each other
|
|
8935
|
+
addDeclaration(identifier, context, init, kind) {
|
|
8936
|
+
const name = identifier.name;
|
|
8937
|
+
const existingVariable = this.hoistedVariables?.get(name) || this.variables.get(name);
|
|
8938
|
+
if (existingVariable) {
|
|
8939
|
+
const existingKind = existingVariable.kind;
|
|
8940
|
+
if ((kind === 'var' || kind === 'function') &&
|
|
8941
|
+
(existingKind === 'var' || existingKind === 'function' || existingKind === 'parameter')) {
|
|
8942
|
+
existingVariable.addDeclaration(identifier, init);
|
|
8943
|
+
return existingVariable;
|
|
8847
8944
|
}
|
|
8945
|
+
context.error(parseAst_js.logRedeclarationError(name), identifier.start);
|
|
8848
8946
|
}
|
|
8947
|
+
const newVariable = new LocalVariable(identifier.name, identifier, init, context, kind);
|
|
8948
|
+
this.variables.set(name, newVariable);
|
|
8949
|
+
return newVariable;
|
|
8849
8950
|
}
|
|
8850
|
-
|
|
8851
|
-
|
|
8951
|
+
}
|
|
8952
|
+
|
|
8953
|
+
class ParameterScope extends ChildScope {
|
|
8954
|
+
constructor(parent, isCatchScope) {
|
|
8955
|
+
super(parent, parent.context);
|
|
8956
|
+
this.parameters = [];
|
|
8957
|
+
this.hasRest = false;
|
|
8958
|
+
this.bodyScope = isCatchScope ? new CatchBodyScope(this) : new FunctionBodyScope(this);
|
|
8852
8959
|
}
|
|
8853
|
-
|
|
8854
|
-
|
|
8855
|
-
|
|
8856
|
-
|
|
8857
|
-
|
|
8858
|
-
|
|
8859
|
-
|
|
8860
|
-
|
|
8861
|
-
|
|
8862
|
-
// otherwise we get many false positives
|
|
8863
|
-
this.variable.module === this.scope.context.module)) {
|
|
8864
|
-
return (this.isTDZAccess = false);
|
|
8865
|
-
}
|
|
8866
|
-
let decl_id;
|
|
8867
|
-
if (this.variable.declarations &&
|
|
8868
|
-
this.variable.declarations.length === 1 &&
|
|
8869
|
-
(decl_id = this.variable.declarations[0]) &&
|
|
8870
|
-
this.start < decl_id.start &&
|
|
8871
|
-
closestParentFunctionOrProgram(this) === closestParentFunctionOrProgram(decl_id)) {
|
|
8872
|
-
// a variable accessed before its declaration
|
|
8873
|
-
// in the same function or at top level of module
|
|
8874
|
-
return (this.isTDZAccess = true);
|
|
8875
|
-
}
|
|
8876
|
-
// We ignore the case where the module is not yet executed because
|
|
8877
|
-
// moduleSideEffects are false.
|
|
8878
|
-
if (!this.variable.initReached && this.scope.context.module.isExecuted) {
|
|
8879
|
-
// Either a const/let TDZ violation or
|
|
8880
|
-
// var use before declaration was encountered.
|
|
8881
|
-
return (this.isTDZAccess = true);
|
|
8960
|
+
/**
|
|
8961
|
+
* Adds a parameter to this scope. Parameters must be added in the correct
|
|
8962
|
+
* order, i.e. from left to right.
|
|
8963
|
+
*/
|
|
8964
|
+
addParameterDeclaration(identifier) {
|
|
8965
|
+
const { name, start } = identifier;
|
|
8966
|
+
const existingParameter = this.variables.get(name);
|
|
8967
|
+
if (existingParameter) {
|
|
8968
|
+
return this.context.error(parseAst_js.logDuplicateArgumentNameError(name), start);
|
|
8882
8969
|
}
|
|
8883
|
-
|
|
8970
|
+
const variable = new ParameterVariable(name, identifier, this.context);
|
|
8971
|
+
this.variables.set(name, variable);
|
|
8972
|
+
// We also add it to the body scope to detect name conflicts with local
|
|
8973
|
+
// variables. We still need the intermediate scope, though, as parameter
|
|
8974
|
+
// defaults are NOT taken from the body scope but from the parameters or
|
|
8975
|
+
// outside scope.
|
|
8976
|
+
this.bodyScope.addHoistedVariable(name, variable);
|
|
8977
|
+
return variable;
|
|
8884
8978
|
}
|
|
8885
|
-
|
|
8886
|
-
this.
|
|
8979
|
+
addParameterVariables(parameters, hasRest) {
|
|
8980
|
+
this.parameters = parameters;
|
|
8981
|
+
for (const parameterList of parameters) {
|
|
8982
|
+
for (const parameter of parameterList) {
|
|
8983
|
+
parameter.alwaysRendered = true;
|
|
8984
|
+
}
|
|
8985
|
+
}
|
|
8986
|
+
this.hasRest = hasRest;
|
|
8887
8987
|
}
|
|
8888
|
-
|
|
8889
|
-
|
|
8890
|
-
|
|
8891
|
-
|
|
8892
|
-
|
|
8893
|
-
|
|
8894
|
-
|
|
8895
|
-
|
|
8896
|
-
|
|
8897
|
-
|
|
8988
|
+
includeCallArguments(context, parameters) {
|
|
8989
|
+
let calledFromTryStatement = false;
|
|
8990
|
+
let argumentIncluded = false;
|
|
8991
|
+
const restParameter = this.hasRest && this.parameters[this.parameters.length - 1];
|
|
8992
|
+
for (const checkedArgument of parameters) {
|
|
8993
|
+
if (checkedArgument instanceof SpreadElement) {
|
|
8994
|
+
for (const argument of parameters) {
|
|
8995
|
+
argument.include(context, false);
|
|
8996
|
+
}
|
|
8997
|
+
break;
|
|
8998
|
+
}
|
|
8999
|
+
}
|
|
9000
|
+
for (let index = parameters.length - 1; index >= 0; index--) {
|
|
9001
|
+
const parameterVariables = this.parameters[index] || restParameter;
|
|
9002
|
+
const argument = parameters[index];
|
|
9003
|
+
if (parameterVariables) {
|
|
9004
|
+
calledFromTryStatement = false;
|
|
9005
|
+
if (parameterVariables.length === 0) {
|
|
9006
|
+
// handle empty destructuring
|
|
9007
|
+
argumentIncluded = true;
|
|
9008
|
+
}
|
|
9009
|
+
else {
|
|
9010
|
+
for (const variable of parameterVariables) {
|
|
9011
|
+
if (variable.included) {
|
|
9012
|
+
argumentIncluded = true;
|
|
9013
|
+
}
|
|
9014
|
+
if (variable.calledFromTryStatement) {
|
|
9015
|
+
calledFromTryStatement = true;
|
|
9016
|
+
}
|
|
9017
|
+
}
|
|
8898
9018
|
}
|
|
8899
9019
|
}
|
|
8900
|
-
|
|
8901
|
-
|
|
8902
|
-
|
|
8903
|
-
|
|
8904
|
-
|
|
9020
|
+
if (!argumentIncluded && argument.shouldBeIncluded(context)) {
|
|
9021
|
+
argumentIncluded = true;
|
|
9022
|
+
}
|
|
9023
|
+
if (argumentIncluded) {
|
|
9024
|
+
argument.include(context, calledFromTryStatement);
|
|
8905
9025
|
}
|
|
8906
9026
|
}
|
|
8907
9027
|
}
|
|
8908
|
-
|
|
8909
|
-
|
|
9028
|
+
}
|
|
9029
|
+
|
|
9030
|
+
class ReturnValueScope extends ParameterScope {
|
|
9031
|
+
constructor() {
|
|
9032
|
+
super(...arguments);
|
|
9033
|
+
this.returnExpression = null;
|
|
9034
|
+
this.returnExpressions = [];
|
|
8910
9035
|
}
|
|
8911
|
-
|
|
8912
|
-
this.
|
|
8913
|
-
if (this.variable instanceof LocalVariable) {
|
|
8914
|
-
this.variable.consolidateInitializers();
|
|
8915
|
-
this.scope.context.requestTreeshakingPass();
|
|
8916
|
-
}
|
|
9036
|
+
addReturnExpression(expression) {
|
|
9037
|
+
this.returnExpressions.push(expression);
|
|
8917
9038
|
}
|
|
8918
|
-
|
|
8919
|
-
if (this.
|
|
8920
|
-
|
|
8921
|
-
|
|
8922
|
-
return this.variable;
|
|
9039
|
+
getReturnExpression() {
|
|
9040
|
+
if (this.returnExpression === null)
|
|
9041
|
+
this.updateReturnExpression();
|
|
9042
|
+
return this.returnExpression;
|
|
8923
9043
|
}
|
|
8924
|
-
|
|
8925
|
-
|
|
8926
|
-
|
|
8927
|
-
|
|
8928
|
-
|
|
8929
|
-
|
|
8930
|
-
|
|
8931
|
-
|
|
8932
|
-
}
|
|
8933
|
-
else {
|
|
8934
|
-
return false;
|
|
9044
|
+
updateReturnExpression() {
|
|
9045
|
+
if (this.returnExpressions.length === 1) {
|
|
9046
|
+
this.returnExpression = this.returnExpressions[0];
|
|
9047
|
+
}
|
|
9048
|
+
else {
|
|
9049
|
+
this.returnExpression = UNKNOWN_EXPRESSION;
|
|
9050
|
+
for (const expression of this.returnExpressions) {
|
|
9051
|
+
expression.deoptimizePath(UNKNOWN_PATH);
|
|
8935
9052
|
}
|
|
8936
9053
|
}
|
|
8937
|
-
return currentPureFunction?.[PureFunctionKey];
|
|
8938
|
-
}
|
|
8939
|
-
}
|
|
8940
|
-
function closestParentFunctionOrProgram(node) {
|
|
8941
|
-
while (node && !/^Program|Function/.test(node.type)) {
|
|
8942
|
-
node = node.parent;
|
|
8943
9054
|
}
|
|
8944
|
-
// one of: ArrowFunctionExpression, FunctionDeclaration, FunctionExpression or Program
|
|
8945
|
-
return node;
|
|
8946
9055
|
}
|
|
8947
9056
|
|
|
8948
9057
|
function treeshakeNode(node, code, start, end) {
|
|
@@ -9237,6 +9346,7 @@ class FunctionBase extends NodeBase {
|
|
|
9237
9346
|
constructor() {
|
|
9238
9347
|
super(...arguments);
|
|
9239
9348
|
this.objectEntity = null;
|
|
9349
|
+
this.parameterVariableValuesDeoptimized = false;
|
|
9240
9350
|
}
|
|
9241
9351
|
get async() {
|
|
9242
9352
|
return isFlagSet(this.flags, 256 /* Flag.async */);
|
|
@@ -9256,6 +9366,25 @@ class FunctionBase extends NodeBase {
|
|
|
9256
9366
|
set generator(value) {
|
|
9257
9367
|
this.flags = setFlag(this.flags, 4194304 /* Flag.generator */, value);
|
|
9258
9368
|
}
|
|
9369
|
+
updateParameterVariableValues(_arguments) {
|
|
9370
|
+
for (let position = 0; position < this.params.length; position++) {
|
|
9371
|
+
const parameter = this.params[position];
|
|
9372
|
+
if (!(parameter instanceof Identifier)) {
|
|
9373
|
+
continue;
|
|
9374
|
+
}
|
|
9375
|
+
const parameterVariable = parameter.variable;
|
|
9376
|
+
const argument = _arguments[position + 1] ?? UNDEFINED_EXPRESSION;
|
|
9377
|
+
parameterVariable.updateKnownValue(argument);
|
|
9378
|
+
}
|
|
9379
|
+
}
|
|
9380
|
+
deoptimizeParameterVariableValues() {
|
|
9381
|
+
for (const parameter of this.params) {
|
|
9382
|
+
if (parameter instanceof Identifier) {
|
|
9383
|
+
const parameterVariable = parameter.variable;
|
|
9384
|
+
parameterVariable.markReassigned();
|
|
9385
|
+
}
|
|
9386
|
+
}
|
|
9387
|
+
}
|
|
9259
9388
|
deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
|
|
9260
9389
|
if (interaction.type === INTERACTION_CALLED) {
|
|
9261
9390
|
const { parameters } = this.scope;
|
|
@@ -9280,6 +9409,7 @@ class FunctionBase extends NodeBase {
|
|
|
9280
9409
|
this.addArgumentToBeDeoptimized(argument);
|
|
9281
9410
|
}
|
|
9282
9411
|
}
|
|
9412
|
+
this.updateParameterVariableValues(args);
|
|
9283
9413
|
}
|
|
9284
9414
|
else {
|
|
9285
9415
|
this.getObjectEntity().deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker);
|
|
@@ -9294,6 +9424,7 @@ class FunctionBase extends NodeBase {
|
|
|
9294
9424
|
for (const parameterList of this.scope.parameters) {
|
|
9295
9425
|
for (const parameter of parameterList) {
|
|
9296
9426
|
parameter.deoptimizePath(UNKNOWN_PATH);
|
|
9427
|
+
parameter.markReassigned();
|
|
9297
9428
|
}
|
|
9298
9429
|
}
|
|
9299
9430
|
}
|
|
@@ -9339,7 +9470,24 @@ class FunctionBase extends NodeBase {
|
|
|
9339
9470
|
}
|
|
9340
9471
|
return false;
|
|
9341
9472
|
}
|
|
9473
|
+
/**
|
|
9474
|
+
* If the function (expression or declaration) is only used as function calls
|
|
9475
|
+
*/
|
|
9476
|
+
onlyFunctionCallUsed() {
|
|
9477
|
+
let variable = null;
|
|
9478
|
+
if (this.parent.type === parseAst_js.VariableDeclarator) {
|
|
9479
|
+
variable = this.parent.id.variable ?? null;
|
|
9480
|
+
}
|
|
9481
|
+
if (this.parent.type === parseAst_js.ExportDefaultDeclaration) {
|
|
9482
|
+
variable = this.parent.variable;
|
|
9483
|
+
}
|
|
9484
|
+
return variable?.getOnlyFunctionCallUsed() ?? false;
|
|
9485
|
+
}
|
|
9342
9486
|
include(context, includeChildrenRecursively) {
|
|
9487
|
+
if (!this.parameterVariableValuesDeoptimized && !this.onlyFunctionCallUsed()) {
|
|
9488
|
+
this.parameterVariableValuesDeoptimized = true;
|
|
9489
|
+
this.deoptimizeParameterVariableValues();
|
|
9490
|
+
}
|
|
9343
9491
|
if (!this.deoptimized)
|
|
9344
9492
|
this.applyDeoptimizations();
|
|
9345
9493
|
this.included = true;
|
|
@@ -9423,6 +9571,11 @@ class ArrowFunctionExpression extends FunctionBase {
|
|
|
9423
9571
|
}
|
|
9424
9572
|
return false;
|
|
9425
9573
|
}
|
|
9574
|
+
onlyFunctionCallUsed() {
|
|
9575
|
+
const isIIFE = this.parent.type === parseAst_js.CallExpression &&
|
|
9576
|
+
this.parent.callee === this;
|
|
9577
|
+
return isIIFE || super.onlyFunctionCallUsed();
|
|
9578
|
+
}
|
|
9426
9579
|
include(context, includeChildrenRecursively) {
|
|
9427
9580
|
super.include(context, includeChildrenRecursively);
|
|
9428
9581
|
for (const parameter of this.params) {
|
|
@@ -10238,6 +10391,10 @@ class MemberExpression extends NodeBase {
|
|
|
10238
10391
|
this.object.deoptimizeArgumentsOnInteractionAtPath(this.accessInteraction, [propertyKey], SHARED_RECURSION_TRACKER);
|
|
10239
10392
|
this.scope.context.requestTreeshakingPass();
|
|
10240
10393
|
}
|
|
10394
|
+
if (this.variable) {
|
|
10395
|
+
this.variable.addUsedPlace(this);
|
|
10396
|
+
this.scope.context.requestTreeshakingPass();
|
|
10397
|
+
}
|
|
10241
10398
|
}
|
|
10242
10399
|
applyAssignmentDeoptimization() {
|
|
10243
10400
|
this.assignmentDeoptimized = true;
|
|
@@ -10436,21 +10593,17 @@ class CallExpression extends CallExpressionBase {
|
|
|
10436
10593
|
};
|
|
10437
10594
|
}
|
|
10438
10595
|
hasEffects(context) {
|
|
10439
|
-
|
|
10440
|
-
|
|
10441
|
-
|
|
10442
|
-
|
|
10443
|
-
|
|
10444
|
-
if (this.annotationPure) {
|
|
10445
|
-
return false;
|
|
10446
|
-
}
|
|
10447
|
-
return (this.callee.hasEffects(context) ||
|
|
10448
|
-
this.callee.hasEffectsOnInteractionAtPath(EMPTY_PATH, this.interaction, context));
|
|
10596
|
+
if (!this.deoptimized)
|
|
10597
|
+
this.applyDeoptimizations();
|
|
10598
|
+
for (const argument of this.arguments) {
|
|
10599
|
+
if (argument.hasEffects(context))
|
|
10600
|
+
return true;
|
|
10449
10601
|
}
|
|
10450
|
-
|
|
10451
|
-
|
|
10452
|
-
this.applyDeoptimizations();
|
|
10602
|
+
if (this.annotationPure) {
|
|
10603
|
+
return false;
|
|
10453
10604
|
}
|
|
10605
|
+
return (this.callee.hasEffects(context) ||
|
|
10606
|
+
this.callee.hasEffectsOnInteractionAtPath(EMPTY_PATH, this.interaction, context));
|
|
10454
10607
|
}
|
|
10455
10608
|
include(context, includeChildrenRecursively) {
|
|
10456
10609
|
if (!this.deoptimized)
|
|
@@ -11111,6 +11264,10 @@ class FunctionDeclaration extends FunctionNode {
|
|
|
11111
11264
|
this.id.variable.isId = true;
|
|
11112
11265
|
}
|
|
11113
11266
|
}
|
|
11267
|
+
onlyFunctionCallUsed() {
|
|
11268
|
+
// call super.onlyFunctionCallUsed for export default anonymous function
|
|
11269
|
+
return this.id?.variable.getOnlyFunctionCallUsed() ?? super.onlyFunctionCallUsed();
|
|
11270
|
+
}
|
|
11114
11271
|
parseNode(esTreeNode) {
|
|
11115
11272
|
if (esTreeNode.id !== null) {
|
|
11116
11273
|
this.id = new Identifier(this, this.scope.parent).parseNode(esTreeNode.id);
|
|
@@ -11372,6 +11529,12 @@ class FunctionExpression extends FunctionNode {
|
|
|
11372
11529
|
}
|
|
11373
11530
|
return super.parseNode(esTreeNode);
|
|
11374
11531
|
}
|
|
11532
|
+
onlyFunctionCallUsed() {
|
|
11533
|
+
const isIIFE = this.parent.type === parseAst_js.CallExpression &&
|
|
11534
|
+
this.parent.callee === this &&
|
|
11535
|
+
(this.id === null || this.id.variable.getOnlyFunctionCallUsed());
|
|
11536
|
+
return isIIFE || super.onlyFunctionCallUsed();
|
|
11537
|
+
}
|
|
11375
11538
|
render(code, options, { renderedSurroundingElement } = parseAst_js.BLANK) {
|
|
11376
11539
|
super.render(code, options);
|
|
11377
11540
|
if (renderedSurroundingElement === parseAst_js.ExpressionStatement) {
|
|
@@ -13177,6 +13340,15 @@ class ExportDefaultVariable extends LocalVariable {
|
|
|
13177
13340
|
this.name = identifier.name;
|
|
13178
13341
|
}
|
|
13179
13342
|
}
|
|
13343
|
+
addUsedPlace(usedPlace) {
|
|
13344
|
+
const original = this.getOriginalVariable();
|
|
13345
|
+
if (original === this) {
|
|
13346
|
+
super.addUsedPlace(usedPlace);
|
|
13347
|
+
}
|
|
13348
|
+
else {
|
|
13349
|
+
original.addUsedPlace(usedPlace);
|
|
13350
|
+
}
|
|
13351
|
+
}
|
|
13180
13352
|
forbidName(name) {
|
|
13181
13353
|
const original = this.getOriginalVariable();
|
|
13182
13354
|
if (original === this) {
|
|
@@ -13450,7 +13622,7 @@ class UpdateExpression extends NodeBase {
|
|
|
13450
13622
|
this.argument.deoptimizePath(EMPTY_PATH);
|
|
13451
13623
|
if (this.argument instanceof Identifier) {
|
|
13452
13624
|
const variable = this.scope.findVariable(this.argument.name);
|
|
13453
|
-
variable.
|
|
13625
|
+
variable.markReassigned();
|
|
13454
13626
|
}
|
|
13455
13627
|
this.scope.context.requestTreeshakingPass();
|
|
13456
13628
|
}
|
|
@@ -19435,7 +19607,7 @@ function addModuleToManualChunk(alias, module, manualChunkAliasByEntry) {
|
|
|
19435
19607
|
|
|
19436
19608
|
function flru (max) {
|
|
19437
19609
|
var num, curr, prev;
|
|
19438
|
-
var limit = max
|
|
19610
|
+
var limit = max ;
|
|
19439
19611
|
|
|
19440
19612
|
function keep(key, value) {
|
|
19441
19613
|
if (++num > limit) {
|