@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.
@@ -1,7 +1,7 @@
1
1
  /*
2
2
  @license
3
- Rollup.js v4.16.4
4
- Tue, 23 Apr 2024 13:14:37 GMT - commit 1c404fa352b70007066e94ff4c1981f8046f8cef
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.16.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
- class LocalVariable extends Variable {
7114
- constructor(name, declarator, init, context, kind) {
7115
- super(name);
7116
- this.init = init;
7117
- this.calledFromTryStatement = false;
7118
- this.additionalInitializers = null;
7119
- this.expressionsToBeDeoptimized = [];
7120
- this.declarations = declarator ? [declarator] : [];
7121
- this.deoptimizationTracker = context.deoptimizationTracker;
7122
- this.module = context.module;
7123
- this.kind = kind;
7124
- }
7125
- addDeclaration(identifier, init) {
7126
- this.declarations.push(identifier);
7127
- this.markInitializersForDeoptimization().push(init);
7128
- }
7129
- consolidateInitializers() {
7130
- if (this.additionalInitializers) {
7131
- for (const initializer of this.additionalInitializers) {
7132
- initializer.deoptimizePath(UNKNOWN_PATH);
7133
- }
7134
- this.additionalInitializers = null;
7135
- }
7136
- }
7137
- deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
7138
- if (this.isReassigned) {
7139
- deoptimizeInteraction(interaction);
7140
- return;
7141
- }
7142
- recursionTracker.withTrackedEntityAtPath(path, this.init, () => this.init.deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker), undefined);
7143
- }
7144
- deoptimizePath(path) {
7145
- if (this.isReassigned ||
7146
- this.deoptimizationTracker.trackEntityAtPathAndGetIfTracked(path, this)) {
7147
- return;
7148
- }
7149
- if (path.length === 0) {
7150
- this.isReassigned = true;
7151
- const expressionsToBeDeoptimized = this.expressionsToBeDeoptimized;
7152
- this.expressionsToBeDeoptimized = parseAst_js.EMPTY_ARRAY;
7153
- for (const expression of expressionsToBeDeoptimized) {
7154
- expression.deoptimizeCache();
7155
- }
7156
- this.init.deoptimizePath(UNKNOWN_PATH);
7157
- }
7158
- else {
7159
- this.init.deoptimizePath(path);
7160
- }
7161
- }
7162
- getLiteralValueAtPath(path, recursionTracker, origin) {
7163
- if (this.isReassigned) {
7164
- return UnknownValue;
7165
- }
7166
- return recursionTracker.withTrackedEntityAtPath(path, this.init, () => {
7167
- this.expressionsToBeDeoptimized.push(origin);
7168
- return this.init.getLiteralValueAtPath(path, recursionTracker, origin);
7169
- }, UnknownValue);
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
- includeCallArguments(context, parameters) {
7226
- if (this.isReassigned || context.includedCallArguments.has(this.init)) {
7227
- for (const argument of parameters) {
7228
- argument.include(context, false);
7229
- }
7230
- }
7231
- else {
7232
- context.includedCallArguments.add(this.init);
7233
- this.init.includeCallArguments(context, parameters);
7234
- context.includedCallArguments.delete(this.init);
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
- markCalledFromTryStatement() {
7238
- this.calledFromTryStatement = true;
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
- markInitializersForDeoptimization() {
7241
- if (this.additionalInitializers === null) {
7242
- this.additionalInitializers = [this.init];
7243
- this.init = UNKNOWN_EXPRESSION;
7244
- this.isReassigned = true;
7245
- }
7246
- return this.additionalInitializers;
7247
- }
7248
- }
7249
-
7250
- const MAX_TRACKED_INTERACTIONS = 20;
7251
- const NO_INTERACTIONS = parseAst_js.EMPTY_ARRAY;
7252
- const UNKNOWN_DEOPTIMIZED_FIELD = new Set([UnknownKey]);
7253
- const EMPTY_PATH_TRACKER = new PathTracker();
7254
- const UNKNOWN_DEOPTIMIZED_ENTITY = new Set([UNKNOWN_EXPRESSION]);
7255
- class ParameterVariable extends LocalVariable {
7256
- constructor(name, declarator, context) {
7257
- super(name, declarator, UNKNOWN_EXPRESSION, context, 'parameter');
7258
- this.deoptimizationInteractions = [];
7259
- this.deoptimizations = new PathTracker();
7260
- this.deoptimizedFields = new Set();
7261
- this.entitiesToBeDeoptimized = new Set();
7262
- }
7263
- addEntityToBeDeoptimized(entity) {
7264
- if (entity === UNKNOWN_EXPRESSION) {
7265
- // As unknown expressions fully deoptimize all interactions, we can clear
7266
- // the interaction cache at this point provided we keep this optimization
7267
- // in mind when adding new interactions
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
- currentGlobal = currentGlobal[pathSegment];
8669
- if (!currentGlobal) {
8670
- return null;
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
- return currentGlobal[ValueProperties];
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
- deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
8684
- switch (interaction.type) {
8685
- // While there is no point in testing these cases as at the moment, they
8686
- // are also covered via other means, we keep them for completeness
8687
- case INTERACTION_ACCESSED:
8688
- case INTERACTION_ASSIGNED: {
8689
- if (!getGlobalAtPath([this.name, ...path].slice(0, -1))) {
8690
- super.deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker);
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
- case INTERACTION_CALLED: {
8695
- const globalAtPath = getGlobalAtPath([this.name, ...path]);
8696
- if (globalAtPath) {
8697
- globalAtPath.deoptimizeArgumentsOnCall(interaction);
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
- else {
8700
- super.deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker);
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
- return;
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
- getLiteralValueAtPath(path, _recursionTracker, _origin) {
8707
- const globalAtPath = getGlobalAtPath([this.name, ...path]);
8708
- return globalAtPath ? globalAtPath.getLiteralValue() : UnknownValue;
8709
- }
8710
- hasEffectsOnInteractionAtPath(path, interaction, context) {
8711
- switch (interaction.type) {
8712
- case INTERACTION_ACCESSED: {
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
- const tdzVariableKinds = new Set(['class', 'const', 'let', 'var', 'using', 'await using']);
8731
- class Identifier extends NodeBase {
8753
+ class Scope {
8732
8754
  constructor() {
8733
- super(...arguments);
8734
- this.variable = null;
8755
+ this.children = [];
8756
+ this.variables = new Map();
8735
8757
  }
8736
- get isTDZAccess() {
8737
- if (!isFlagSet(this.flags, 4 /* Flag.tdzAccessDefined */)) {
8738
- return null;
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
- return isFlagSet(this.flags, 8 /* Flag.tdzAccess */);
8781
+ const newVariable = new LocalVariable(identifier.name, identifier, init, context, kind);
8782
+ this.variables.set(name, newVariable);
8783
+ return newVariable;
8741
8784
  }
8742
- set isTDZAccess(value) {
8743
- this.flags = setFlag(this.flags, 4 /* Flag.tdzAccessDefined */, true);
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
- addExportedVariables(variables, exportNamesByVariable) {
8747
- if (exportNamesByVariable.has(this.variable)) {
8748
- variables.push(this.variable);
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
- bind() {
8752
- if (!this.variable && is_reference(this, this.parent)) {
8753
- this.variable = this.scope.findVariable(this.name);
8754
- this.variable.addReference(this);
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
- declare(kind, init) {
8758
- let variable;
8759
- const { treeshake } = this.scope.context.options;
8760
- switch (kind) {
8761
- case 'var': {
8762
- variable = this.scope.addDeclaration(this, this.scope.context, init, kind);
8763
- if (treeshake && treeshake.correctVarValueBeforeDeclaration) {
8764
- // Necessary to make sure the init is deoptimized. We cannot call deoptimizePath here.
8765
- variable.markInitializersForDeoptimization();
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
- /* istanbul ignore next */
8787
- default: {
8788
- /* istanbul ignore next */
8789
- throw new Error(`Internal Error: Unexpected identifier kind ${kind}.`);
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
- deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
8795
- this.variable.deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker);
8844
+ contains(name) {
8845
+ return this.variables.has(name) || this.parent.contains(name);
8796
8846
  }
8797
- deoptimizePath(path) {
8798
- if (path.length === 0 && !this.scope.contains(this.name)) {
8799
- this.disallowImportReassignment();
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
- getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin) {
8809
- const [expression, isPure] = this.getVariableRespectingTDZ().getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin);
8810
- return [expression, isPure || this.isPureFunction(path)];
8866
+ findLexicalBoundary() {
8867
+ return this.parent.findLexicalBoundary();
8811
8868
  }
8812
- hasEffects(context) {
8813
- if (!this.deoptimized)
8814
- this.applyDeoptimizations();
8815
- if (this.isPossibleTDZ() && this.variable.kind !== 'var') {
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
- return (this.scope.context.options.treeshake
8819
- .unknownGlobalSideEffects &&
8820
- this.variable instanceof GlobalVariable &&
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
- hasEffectsOnInteractionAtPath(path, interaction, context) {
8825
- switch (interaction.type) {
8826
- case INTERACTION_ACCESSED: {
8827
- return (this.variable !== null &&
8828
- !this.isPureFunction(path) &&
8829
- this.getVariableRespectingTDZ().hasEffectsOnInteractionAtPath(path, interaction, context));
8830
- }
8831
- case INTERACTION_ASSIGNED: {
8832
- return (path.length > 0 ? this.getVariableRespectingTDZ() : this.variable).hasEffectsOnInteractionAtPath(path, interaction, context);
8833
- }
8834
- case INTERACTION_CALLED: {
8835
- return (!this.isPureFunction(path) &&
8836
- this.getVariableRespectingTDZ().hasEffectsOnInteractionAtPath(path, interaction, context));
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
- include() {
8841
- if (!this.deoptimized)
8842
- this.applyDeoptimizations();
8843
- if (!this.included) {
8844
- this.included = true;
8845
- if (this.variable !== null) {
8846
- this.scope.context.includeVariableInModule(this.variable);
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
- includeCallArguments(context, parameters) {
8851
- this.variable.includeCallArguments(context, parameters);
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
- isPossibleTDZ() {
8854
- // return cached value to avoid issues with the next tree-shaking pass
8855
- const cachedTdzAccess = this.isTDZAccess;
8856
- if (cachedTdzAccess !== null)
8857
- return cachedTdzAccess;
8858
- if (!(this.variable instanceof LocalVariable &&
8859
- this.variable.kind &&
8860
- tdzVariableKinds.has(this.variable.kind) &&
8861
- // we ignore possible TDZs due to circular module dependencies as
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
- return (this.isTDZAccess = false);
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
- markDeclarationReached() {
8886
- this.variable.initReached = true;
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
- render(code, { snippets: { getPropertyAccess }, useOriginalName }, { renderedParentType, isCalleeOfRenderedParent, isShorthandProperty } = parseAst_js.BLANK) {
8889
- if (this.variable) {
8890
- const name = this.variable.getName(getPropertyAccess, useOriginalName);
8891
- if (name !== this.name) {
8892
- code.overwrite(this.start, this.end, name, {
8893
- contentOnly: true,
8894
- storeName: true
8895
- });
8896
- if (isShorthandProperty) {
8897
- code.prependRight(this.start, `${this.name}: `);
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
- // In strict mode, any variable named "eval" must be the actual "eval" function
8901
- if (name === 'eval' &&
8902
- renderedParentType === parseAst_js.CallExpression &&
8903
- isCalleeOfRenderedParent) {
8904
- code.appendRight(this.start, '0, ');
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
- disallowImportReassignment() {
8909
- return this.scope.context.error(parseAst_js.logIllegalImportReassignment(this.name, this.scope.context.module.id), this.start);
9028
+ }
9029
+
9030
+ class ReturnValueScope extends ParameterScope {
9031
+ constructor() {
9032
+ super(...arguments);
9033
+ this.returnExpression = null;
9034
+ this.returnExpressions = [];
8910
9035
  }
8911
- applyDeoptimizations() {
8912
- this.deoptimized = true;
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
- getVariableRespectingTDZ() {
8919
- if (this.isPossibleTDZ()) {
8920
- return UNKNOWN_EXPRESSION;
8921
- }
8922
- return this.variable;
9039
+ getReturnExpression() {
9040
+ if (this.returnExpression === null)
9041
+ this.updateReturnExpression();
9042
+ return this.returnExpression;
8923
9043
  }
8924
- isPureFunction(path) {
8925
- let currentPureFunction = this.scope.context.manualPureFunctions[this.name];
8926
- for (const segment of path) {
8927
- if (currentPureFunction) {
8928
- if (currentPureFunction[PureFunctionKey]) {
8929
- return true;
8930
- }
8931
- currentPureFunction = currentPureFunction[segment];
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
- try {
10440
- for (const argument of this.arguments) {
10441
- if (argument.hasEffects(context))
10442
- return true;
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
- finally {
10451
- if (!this.deoptimized)
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.isReassigned = true;
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 || 1;
19610
+ var limit = max ;
19439
19611
 
19440
19612
  function keep(key, value) {
19441
19613
  if (++num > limit) {