diff --git a/packages/babel-parser/src/parser/expression.js b/packages/babel-parser/src/parser/expression.js index 23d131fd0d71..07228f8bf72c 100644 --- a/packages/babel-parser/src/parser/expression.js +++ b/packages/babel-parser/src/parser/expression.js @@ -2657,7 +2657,10 @@ export default class ExpressionParser extends LValParser { const node = this.startNode(); this.next(); // eat "module" this.expect(tt.braceL); - const revertScopes = this.initializeScopes(); + + const revertScopes = this.initializeScopes(/** inModule */ true); + this.enterInitialScopes(); + const program = this.startNode(); try { node.body = this.parseProgram(program, tt.braceR, "module"); diff --git a/packages/babel-parser/src/parser/index.js b/packages/babel-parser/src/parser/index.js index 6e9446907527..2db11faf491c 100644 --- a/packages/babel-parser/src/parser/index.js +++ b/packages/babel-parser/src/parser/index.js @@ -5,14 +5,7 @@ import type { File /*::, JSXOpeningElement */ } from "../types"; import type { PluginList } from "../plugin-utils"; import { getOptions } from "../options"; import StatementParser from "./statement"; -import { SCOPE_PROGRAM } from "../util/scopeflags"; import ScopeHandler from "../util/scope"; -import ClassScopeHandler from "../util/class-scope"; -import ExpressionScopeHandler from "../util/expression-scope"; -import ProductionParameterHandler, { - PARAM_AWAIT, - PARAM, -} from "../util/production-parameter"; export type PluginsMap = Map; @@ -28,14 +21,8 @@ export default class Parser extends StatementParser { options = getOptions(options); super(options, input); - const ScopeHandler = this.getScopeHandler(); - this.options = options; - this.inModule = this.options.sourceType === "module"; - this.scope = new ScopeHandler(this.raise.bind(this), this.inModule); - this.prodParam = new ProductionParameterHandler(); - this.classScope = new ClassScopeHandler(this.raise.bind(this)); - this.expressionScope = new ExpressionScopeHandler(this.raise.bind(this)); + this.initializeScopes(); this.plugins = pluginsMap(this.options.plugins); this.filename = options.sourceFilename; } @@ -46,12 +33,7 @@ export default class Parser extends StatementParser { } parse(): File { - let paramFlags = PARAM; - if (this.hasPlugin("topLevelAwait") && this.inModule) { - paramFlags |= PARAM_AWAIT; - } - this.scope.enter(SCOPE_PROGRAM); - this.prodParam.enter(paramFlags); + this.enterInitialScopes(); const file = this.startNode(); const program = this.startNode(); this.nextToken(); diff --git a/packages/babel-parser/src/parser/util.js b/packages/babel-parser/src/parser/util.js index c9be7d3b0c7e..7be6eca4dd15 100644 --- a/packages/babel-parser/src/parser/util.js +++ b/packages/babel-parser/src/parser/util.js @@ -7,8 +7,12 @@ import type { Node } from "../types"; import { lineBreak } from "../util/whitespace"; import { isIdentifierChar } from "../util/identifier"; import ClassScopeHandler from "../util/class-scope"; +import ExpressionScopeHandler from "../util/expression-scope"; import { SCOPE_PROGRAM } from "../util/scopeflags"; -import { PARAM_AWAIT, PARAM } from "../util/production-parameter"; +import ProductionParameterHandler, { + PARAM_AWAIT, + PARAM, +} from "../util/production-parameter"; import { Errors } from "./error"; type TryParse = { @@ -308,33 +312,53 @@ export default class UtilParser extends Tokenizer { return node.type === "ObjectMethod"; } - initializeScopes() { + initializeScopes(inModule: boolean = this.options.sourceType === "module") { + // Initialize state const oldLabels = this.state.labels; this.state.labels = []; + const oldExportedIdentifiers = this.state.exportedIdentifiers; this.state.exportedIdentifiers = []; - this.scope.enter(SCOPE_PROGRAM); - const oldUndefinedExports = this.scope.undefinedExports; - this.scope.undefinedExports = new Map(); - let paramFlags = PARAM; - if (this.hasPlugin("topLevelAwait")) { - paramFlags |= PARAM_AWAIT; - } - this.prodParam.enter(paramFlags); + + // initialize scopes const oldInModule = this.inModule; - this.inModule = true; + this.inModule = inModule; + + const oldScope = this.scope; + const ScopeHandler = this.getScopeHandler(); + this.scope = new ScopeHandler(this.raise.bind(this), this.inModule); + + const oldProdParam = this.prodParam; + this.prodParam = new ProductionParameterHandler(); + const oldClassScope = this.classScope; this.classScope = new ClassScopeHandler(this.raise.bind(this)); + + const oldExpressionScope = this.expressionScope; + this.expressionScope = new ExpressionScopeHandler(this.raise.bind(this)); + return () => { - this.scope.exit(); - this.scope.undefinedExports = oldUndefinedExports; - this.prodParam.exit(); - this.inModule = oldInModule; + // Revert state this.state.labels = oldLabels; this.state.exportedIdentifiers = oldExportedIdentifiers; + + // Revert scopes + this.inModule = oldInModule; + this.scope = oldScope; + this.prodParam = oldProdParam; this.classScope = oldClassScope; + this.expressionScope = oldExpressionScope; }; } + + enterInitialScopes() { + let paramFlags = PARAM; + if (this.hasPlugin("topLevelAwait") && this.inModule) { + paramFlags |= PARAM_AWAIT; + } + this.scope.enter(SCOPE_PROGRAM); + this.prodParam.enter(paramFlags); + } } /**