diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 1c5194054ca..24769afd5d4 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -2134,7 +2134,7 @@ namespace ts { if (node.variableDeclaration) { writeToken(SyntaxKind.OpenParenToken, openParenPos); emit(node.variableDeclaration); - writeToken(SyntaxKind.CloseParenToken, node.variableDeclaration ? node.variableDeclaration.end : openParenPos); + writeToken(SyntaxKind.CloseParenToken, node.variableDeclaration.end); write(" "); } emit(node.block); diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index 34727e4c414..47df0a9bdc2 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -2128,14 +2128,14 @@ namespace ts { : node; } - export function createCatchClause(variableDeclaration: string | VariableDeclaration, block: Block) { + export function createCatchClause(variableDeclaration: string | VariableDeclaration | undefined, block: Block) { const node = createSynthesizedNode(SyntaxKind.CatchClause); node.variableDeclaration = typeof variableDeclaration === "string" ? createVariableDeclaration(variableDeclaration) : variableDeclaration; node.block = block; return node; } - export function updateCatchClause(node: CatchClause, variableDeclaration: VariableDeclaration, block: Block) { + export function updateCatchClause(node: CatchClause, variableDeclaration: VariableDeclaration | undefined, block: Block) { return node.variableDeclaration !== variableDeclaration || node.block !== block ? updateNode(createCatchClause(variableDeclaration, block), node) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 12c516c88b0..4547df15790 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -4783,6 +4783,10 @@ namespace ts { result.variableDeclaration = parseVariableDeclaration(); parseExpected(SyntaxKind.CloseParenToken); } + else { + // Keep shape of node to not avoid degrading performance. + result.variableDeclaration = undefined; + } result.block = parseBlock(/*ignoreMissingOpenBrace*/ false); return finishNode(result); diff --git a/src/compiler/transformers/es2015.ts b/src/compiler/transformers/es2015.ts index 51733524699..2b0b175e2a5 100644 --- a/src/compiler/transformers/es2015.ts +++ b/src/compiler/transformers/es2015.ts @@ -3173,7 +3173,7 @@ namespace ts { function visitCatchClause(node: CatchClause): CatchClause { const ancestorFacts = enterSubtree(HierarchyFacts.BlockScopeExcludes, HierarchyFacts.BlockScopeIncludes); let updated: CatchClause; - Debug.assert(!!node.variableDeclaration, "Catch clauses should always be present when downleveling ES2015 code."); + Debug.assert(!!node.variableDeclaration, "Catch clause variable should always be present when downleveling ES2015."); if (isBindingPattern(node.variableDeclaration.name)) { const temp = createTempVariable(/*recordTempVariable*/ undefined); const newVariableDeclaration = createVariableDeclaration(temp); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 9cf8e6fdf00..ca70a6fe209 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1807,7 +1807,7 @@ namespace ts { export interface CatchClause extends Node { kind: SyntaxKind.CatchClause; - parent?: TryStatement; // We make this optional to parse missing try statements + parent?: TryStatement; variableDeclaration?: VariableDeclaration; block: Block; }