diff --git a/src/ast/nodes/Identifier.ts b/src/ast/nodes/Identifier.ts index 63e6a5149d9..4ce676130f2 100644 --- a/src/ast/nodes/Identifier.ts +++ b/src/ast/nodes/Identifier.ts @@ -60,7 +60,7 @@ export default class Identifier extends NodeBase implements PatternNode { variable = this.scope.addDeclaration(this, this.context, init, true); if (treeshake && treeshake.correctVarValueBeforeDeclaration) { // Necessary to make sure the init is deoptimized. We cannot call deoptimizePath here. - this.scope.addDeclaration(this, this.context, UNDEFINED_EXPRESSION, true); + variable.markInitializersForDeoptimization(); } break; case 'function': diff --git a/src/ast/scopes/BlockScope.ts b/src/ast/scopes/BlockScope.ts index ee694c790b5..7029bf00764 100644 --- a/src/ast/scopes/BlockScope.ts +++ b/src/ast/scopes/BlockScope.ts @@ -1,7 +1,6 @@ import { AstContext } from '../../Module'; import Identifier from '../nodes/Identifier'; import { ExpressionEntity } from '../nodes/shared/Expression'; -import { UNDEFINED_EXPRESSION } from '../values'; import LocalVariable from '../variables/LocalVariable'; import ChildScope from './ChildScope'; @@ -13,10 +12,11 @@ export default class BlockScope extends ChildScope { isHoisted: boolean ): LocalVariable { if (isHoisted) { - this.parent.addDeclaration(identifier, context, init, isHoisted); + const variable = this.parent.addDeclaration(identifier, context, init, isHoisted); // Necessary to make sure the init is deoptimized for conditional declarations. // We cannot call deoptimizePath here. - return this.parent.addDeclaration(identifier, context, UNDEFINED_EXPRESSION, isHoisted); + variable.markInitializersForDeoptimization(); + return variable; } else { return super.addDeclaration(identifier, context, init, false); } diff --git a/src/ast/variables/LocalVariable.ts b/src/ast/variables/LocalVariable.ts index 7401001757a..dc5ef57f7da 100644 --- a/src/ast/variables/LocalVariable.ts +++ b/src/ast/variables/LocalVariable.ts @@ -21,7 +21,6 @@ import Variable from './Variable'; const MAX_PATH_DEPTH = 7; export default class LocalVariable extends Variable { - additionalInitializers: ExpressionEntity[] | null = null; calledFromTryStatement = false; declarations: (Identifier | ExportDefaultDeclaration)[]; init: ExpressionEntity | null; @@ -30,6 +29,7 @@ export default class LocalVariable extends Variable { // Caching and deoptimization: // We track deoptimization when we do not return something unknown protected deoptimizationTracker: PathTracker; + private additionalInitializers: ExpressionEntity[] | null = null; private expressionsToBeDeoptimized: DeoptimizableEntity[] = []; constructor( @@ -47,13 +47,9 @@ export default class LocalVariable extends Variable { addDeclaration(identifier: Identifier, init: ExpressionEntity | null): void { this.declarations.push(identifier); - if (this.additionalInitializers === null) { - this.additionalInitializers = this.init === null ? [] : [this.init]; - this.init = UNKNOWN_EXPRESSION; - this.isReassigned = true; - } + const additionalInitializers = this.markInitializersForDeoptimization(); if (init !== null) { - this.additionalInitializers.push(init); + additionalInitializers.push(init); } } @@ -212,4 +208,13 @@ export default class LocalVariable extends Variable { markCalledFromTryStatement(): void { this.calledFromTryStatement = true; } + + markInitializersForDeoptimization(): ExpressionEntity[] { + if (this.additionalInitializers === null) { + this.additionalInitializers = this.init === null ? [] : [this.init]; + this.init = UNKNOWN_EXPRESSION; + this.isReassigned = true; + } + return this.additionalInitializers; + } }