From b17bd97e71aee2c8b1bceb1ea94533b0d272aafe Mon Sep 17 00:00:00 2001 From: Tingan Ho Date: Sun, 30 Jul 2017 10:29:09 +0200 Subject: [PATCH 01/17] Clean up --- src/compiler/checker.ts | 2 +- src/compiler/types.ts | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 4de0c7a2a6c37..f3979d8044181 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -481,7 +481,7 @@ namespace ts { Type, ResolvedBaseConstructorType, DeclaredType, - ResolvedReturnType + ResolvedReturnType, } const enum CheckMode { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 09f1b5cfcc53c..fb7a6745d0c19 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -4001,7 +4001,6 @@ namespace ts { ContainsBindingPattern = 1 << 23, ContainsYield = 1 << 24, ContainsHoistedDeclarationOrCompletion = 1 << 25, - ContainsDynamicImport = 1 << 26, // Please leave this as 1 << 29. From 99c662b5e4e2548ea6607c027ba7d2373ec2ff45 Mon Sep 17 00:00:00 2001 From: Tingan Ho Date: Sun, 30 Jul 2017 10:29:30 +0200 Subject: [PATCH 02/17] Add diagnostics --- src/compiler/diagnosticMessages.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 3b4b0ddf66711..fbd91f33905f9 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -2196,6 +2196,10 @@ "category": "Error", "code": 2713 }, + "Duplicate identifier '_ignoredCatchParameter'. Compiler uses the parameter declaration '_ignoredCatchParameter' to bind ignored catched exceptions.": { + "category": "Error", + "code": 2714 + }, "Import declaration '{0}' is using private name '{1}'.": { "category": "Error", From b917eb022558af24b7a8e01f8bff4c249480f012 Mon Sep 17 00:00:00 2001 From: Tingan Ho Date: Sun, 30 Jul 2017 10:30:59 +0200 Subject: [PATCH 03/17] Adds optional catch parameter into the compiler --- src/compiler/binder.ts | 5 ++++- src/compiler/checker.ts | 12 ++++++++++++ src/compiler/emitter.ts | 10 ++++++---- src/compiler/parser.ts | 5 +++-- src/compiler/types.ts | 4 ++-- 5 files changed, 27 insertions(+), 9 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 2fbd0c3e1412a..aa42d1b251bcc 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -2921,7 +2921,10 @@ namespace ts { function computeCatchClause(node: CatchClause, subtreeFlags: TransformFlags) { let transformFlags = subtreeFlags; - if (node.variableDeclaration && isBindingPattern(node.variableDeclaration.name)) { + if (!node.variableDeclaration) { + transformFlags |= TransformFlags.AssertESNext; + } + else if (/* node.variableDeclaration && */ isBindingPattern(node.variableDeclaration.name)) { transformFlags |= TransformFlags.AssertES2015; } diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f3979d8044181..8c7e7abef1c56 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -20885,6 +20885,18 @@ namespace ts { } } } + else if (/* !catchClause.variableDeclaration && */ languageVersion < ScriptTarget.ESNext) { + const blockLocals = catchClause.block.locals; + debugger; + if (blockLocals) { + forEachKey(blockLocals, caughtName => { + if (caughtName === "_ignoredCatchParameter") { + const localSymbol = blockLocals.get(caughtName); + grammarErrorOnNode(localSymbol.valueDeclaration, Diagnostics.Duplicate_identifier_ignoredCatchParameter_Compiler_uses_the_parameter_declaration_ignoredCatchParameter_to_bind_ignored_catched_exceptions); + } + }); + } + } checkBlock(catchClause.block); } diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index de08b209d3e4e..1c5194054cacd 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -2131,10 +2131,12 @@ namespace ts { function emitCatchClause(node: CatchClause) { const openParenPos = writeToken(SyntaxKind.CatchKeyword, node.pos); write(" "); - writeToken(SyntaxKind.OpenParenToken, openParenPos); - emit(node.variableDeclaration); - writeToken(SyntaxKind.CloseParenToken, node.variableDeclaration ? node.variableDeclaration.end : openParenPos); - write(" "); + if (node.variableDeclaration) { + writeToken(SyntaxKind.OpenParenToken, openParenPos); + emit(node.variableDeclaration); + writeToken(SyntaxKind.CloseParenToken, node.variableDeclaration ? node.variableDeclaration.end : openParenPos); + write(" "); + } emit(node.block); } diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 34670cd28349a..12c516c88b03e 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -4778,11 +4778,12 @@ namespace ts { function parseCatchClause(): CatchClause { const result = createNode(SyntaxKind.CatchClause); parseExpected(SyntaxKind.CatchKeyword); - if (parseExpected(SyntaxKind.OpenParenToken)) { + + if (parseOptional(SyntaxKind.OpenParenToken)) { result.variableDeclaration = parseVariableDeclaration(); + parseExpected(SyntaxKind.CloseParenToken); } - parseExpected(SyntaxKind.CloseParenToken); result.block = parseBlock(/*ignoreMissingOpenBrace*/ false); return finishNode(result); } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index fb7a6745d0c19..5210b89eb1fbc 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1807,8 +1807,8 @@ namespace ts { export interface CatchClause extends Node { kind: SyntaxKind.CatchClause; - parent?: TryStatement; - variableDeclaration: VariableDeclaration; + parent: TryStatement; + variableDeclaration?: VariableDeclaration; block: Block; } From 148a494c90d0849ad94de02f34975dd8960e22be Mon Sep 17 00:00:00 2001 From: Tingan Ho Date: Sun, 30 Jul 2017 10:31:31 +0200 Subject: [PATCH 04/17] Adds transformers for ignored catch parameter --- src/compiler/transformers/es2015.ts | 2 +- src/compiler/transformers/esnext.ts | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/compiler/transformers/es2015.ts b/src/compiler/transformers/es2015.ts index f97de018d4ad0..ebfd0b0069f97 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; - if (isBindingPattern(node.variableDeclaration.name)) { + if (node.variableDeclaration && isBindingPattern(node.variableDeclaration.name)) { const temp = createTempVariable(/*recordTempVariable*/ undefined); const newVariableDeclaration = createVariableDeclaration(temp); setTextRange(newVariableDeclaration, node.variableDeclaration); diff --git a/src/compiler/transformers/esnext.ts b/src/compiler/transformers/esnext.ts index 3d8840019326d..597b9d55b1648 100644 --- a/src/compiler/transformers/esnext.ts +++ b/src/compiler/transformers/esnext.ts @@ -101,6 +101,8 @@ namespace ts { return visitExpressionStatement(node as ExpressionStatement); case SyntaxKind.ParenthesizedExpression: return visitParenthesizedExpression(node as ParenthesizedExpression, noDestructuringValue); + case SyntaxKind.CatchClause: + return visitCatchClause(node as CatchClause); default: return visitEachChild(node, visitor, context); } @@ -212,6 +214,13 @@ namespace ts { return visitEachChild(node, noDestructuringValue ? visitorNoDestructuringValue : visitor, context); } + function visitCatchClause(node: CatchClause): CatchClause { + if (!node.variableDeclaration) { + return updateCatchClause(node, createVariableDeclaration("_ignoredCatchParameter"), node.block); + } + return visitEachChild(node, visitor, context); + } + /** * Visits a BinaryExpression that contains a destructuring assignment. * From e349943c07e4f0ca52110d109705ba4797c86e74 Mon Sep 17 00:00:00 2001 From: Tingan Ho Date: Sun, 30 Jul 2017 10:32:39 +0200 Subject: [PATCH 05/17] Add tests --- .../statements/tryStatements/invalidTryStatements.ts | 5 +++++ .../statements/tryStatements/tryStatements.ts | 9 ++++----- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/tests/cases/conformance/statements/tryStatements/invalidTryStatements.ts b/tests/cases/conformance/statements/tryStatements/invalidTryStatements.ts index c838cf45f6948..6ecdfe1065609 100644 --- a/tests/cases/conformance/statements/tryStatements/invalidTryStatements.ts +++ b/tests/cases/conformance/statements/tryStatements/invalidTryStatements.ts @@ -8,5 +8,10 @@ function fn() { try { } catch (z: any) { } try { } catch (a: number) { } try { } catch (y: string) { } + + + try { } catch { + let _ignoredCatchParameter; // Should error since we downlevel emit this variable. + } } diff --git a/tests/cases/conformance/statements/tryStatements/tryStatements.ts b/tests/cases/conformance/statements/tryStatements/tryStatements.ts index 691c046d6d14d..42f549e6911ad 100644 --- a/tests/cases/conformance/statements/tryStatements/tryStatements.ts +++ b/tests/cases/conformance/statements/tryStatements/tryStatements.ts @@ -1,11 +1,10 @@ + function fn() { - try { + try { } catch { } - } catch (x) { - var x: any; - } + try { } catch (x) { var x: any; } try { } finally { } - try { }catch(z){ } finally { } + try { } catch(z) { } finally { } } \ No newline at end of file From 90ea10e45e7fb49f1fe3eb26e4f5bbc634256d07 Mon Sep 17 00:00:00 2001 From: Tingan Ho Date: Sun, 30 Jul 2017 10:33:22 +0200 Subject: [PATCH 06/17] Accept baselines --- ...tructorWithIncompleteTypeAnnotation.errors.txt | 4 ++-- .../constructorWithIncompleteTypeAnnotation.js | 2 +- .../emitter.ignoredCatchParameter.esnext.js | 11 +++++++++++ .../emitter.ignoredCatchParameter.esnext.symbols | 7 +++++++ .../emitter.ignoredCatchParameter.esnext.types | 7 +++++++ .../reference/invalidTryStatements.errors.txt | 10 +++++++++- tests/baselines/reference/invalidTryStatements.js | 9 +++++++++ .../reference/invalidTryStatements2.errors.txt | 5 +---- .../baselines/reference/invalidTryStatements2.js | 2 +- tests/baselines/reference/tryStatements.js | 13 ++++++------- tests/baselines/reference/tryStatements.symbols | 15 ++++++--------- tests/baselines/reference/tryStatements.types | 9 +++------ 12 files changed, 63 insertions(+), 31 deletions(-) create mode 100644 tests/baselines/reference/emitter.ignoredCatchParameter.esnext.js create mode 100644 tests/baselines/reference/emitter.ignoredCatchParameter.esnext.symbols create mode 100644 tests/baselines/reference/emitter.ignoredCatchParameter.esnext.types diff --git a/tests/baselines/reference/constructorWithIncompleteTypeAnnotation.errors.txt b/tests/baselines/reference/constructorWithIncompleteTypeAnnotation.errors.txt index 1d37b20a3b3e8..708f175c00250 100644 --- a/tests/baselines/reference/constructorWithIncompleteTypeAnnotation.errors.txt +++ b/tests/baselines/reference/constructorWithIncompleteTypeAnnotation.errors.txt @@ -34,7 +34,7 @@ tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(138,13): error T tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(141,32): error TS1005: '{' expected. tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(143,13): error TS1005: 'try' expected. tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(159,24): error TS1109: Expression expected. -tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(159,30): error TS1005: '(' expected. +tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(159,30): error TS1005: '{' expected. tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(159,31): error TS2304: Cannot find name 'Property'. tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(166,13): error TS2365: Operator '+=' cannot be applied to types 'number' and 'void'. tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(180,40): error TS2447: The '^' operator is not allowed for boolean types. Consider using '!==' instead. @@ -323,7 +323,7 @@ tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(261,1): error TS ~~~~~ !!! error TS1109: Expression expected. ~ -!!! error TS1005: '(' expected. +!!! error TS1005: '{' expected. ~~~~~~~~ !!! error TS2304: Cannot find name 'Property'. retVal += c.Member(); diff --git a/tests/baselines/reference/constructorWithIncompleteTypeAnnotation.js b/tests/baselines/reference/constructorWithIncompleteTypeAnnotation.js index 8e9dc6da68831..013692a488949 100644 --- a/tests/baselines/reference/constructorWithIncompleteTypeAnnotation.js +++ b/tests/baselines/reference/constructorWithIncompleteTypeAnnotation.js @@ -441,7 +441,7 @@ var BasicFeatures = (function () { var xx = c; retVal += ; try { } - catch () { } + catch (_ignoredCatchParameter) { } Property; retVal += c.Member(); retVal += xx.Foo() ? 0 : 1; diff --git a/tests/baselines/reference/emitter.ignoredCatchParameter.esnext.js b/tests/baselines/reference/emitter.ignoredCatchParameter.esnext.js new file mode 100644 index 0000000000000..0f9254fd3cbaf --- /dev/null +++ b/tests/baselines/reference/emitter.ignoredCatchParameter.esnext.js @@ -0,0 +1,11 @@ +//// [emitter.ignoredCatchParameter.esnext.ts] +function fn() { + try {} catch {} +} + + +//// [emitter.ignoredCatchParameter.esnext.js] +function fn() { + try { } + catch { } +} diff --git a/tests/baselines/reference/emitter.ignoredCatchParameter.esnext.symbols b/tests/baselines/reference/emitter.ignoredCatchParameter.esnext.symbols new file mode 100644 index 0000000000000..78838a33011ac --- /dev/null +++ b/tests/baselines/reference/emitter.ignoredCatchParameter.esnext.symbols @@ -0,0 +1,7 @@ +=== tests/cases/conformance/emitter/esnext/noCatchParameter/emitter.ignoredCatchParameter.esnext.ts === +function fn() { +>fn : Symbol(fn, Decl(emitter.ignoredCatchParameter.esnext.ts, 0, 0)) + + try {} catch {} +} + diff --git a/tests/baselines/reference/emitter.ignoredCatchParameter.esnext.types b/tests/baselines/reference/emitter.ignoredCatchParameter.esnext.types new file mode 100644 index 0000000000000..06bf4ab268274 --- /dev/null +++ b/tests/baselines/reference/emitter.ignoredCatchParameter.esnext.types @@ -0,0 +1,7 @@ +=== tests/cases/conformance/emitter/esnext/noCatchParameter/emitter.ignoredCatchParameter.esnext.ts === +function fn() { +>fn : () => void + + try {} catch {} +} + diff --git a/tests/baselines/reference/invalidTryStatements.errors.txt b/tests/baselines/reference/invalidTryStatements.errors.txt index a2f8a7bac0c96..08dc5f1dfa0d0 100644 --- a/tests/baselines/reference/invalidTryStatements.errors.txt +++ b/tests/baselines/reference/invalidTryStatements.errors.txt @@ -1,9 +1,10 @@ tests/cases/conformance/statements/tryStatements/invalidTryStatements.ts(8,23): error TS1196: Catch clause variable cannot have a type annotation. tests/cases/conformance/statements/tryStatements/invalidTryStatements.ts(9,23): error TS1196: Catch clause variable cannot have a type annotation. tests/cases/conformance/statements/tryStatements/invalidTryStatements.ts(10,23): error TS1196: Catch clause variable cannot have a type annotation. +tests/cases/conformance/statements/tryStatements/invalidTryStatements.ts(14,13): error TS2714: Duplicate identifier '_ignoredCatchParameter'. Compiler uses the parameter declaration '_ignoredCatchParameter' to bind ignored catched exceptions. -==== tests/cases/conformance/statements/tryStatements/invalidTryStatements.ts (3 errors) ==== +==== tests/cases/conformance/statements/tryStatements/invalidTryStatements.ts (4 errors) ==== function fn() { try { } catch (x) { @@ -20,6 +21,13 @@ tests/cases/conformance/statements/tryStatements/invalidTryStatements.ts(10,23): try { } catch (y: string) { } ~~~~~~ !!! error TS1196: Catch clause variable cannot have a type annotation. + + + try { } catch { + let _ignoredCatchParameter; // Should error since we downlevel emit this variable. + ~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2714: Duplicate identifier '_ignoredCatchParameter'. Compiler uses the parameter declaration '_ignoredCatchParameter' to bind ignored catched exceptions. + } } \ No newline at end of file diff --git a/tests/baselines/reference/invalidTryStatements.js b/tests/baselines/reference/invalidTryStatements.js index 343ad6e058400..1436c83ae07dc 100644 --- a/tests/baselines/reference/invalidTryStatements.js +++ b/tests/baselines/reference/invalidTryStatements.js @@ -9,6 +9,11 @@ function fn() { try { } catch (z: any) { } try { } catch (a: number) { } try { } catch (y: string) { } + + + try { } catch { + let _ignoredCatchParameter; // Should error since we downlevel emit this variable. + } } @@ -27,4 +32,8 @@ function fn() { catch (a) { } try { } catch (y) { } + try { } + catch (_ignoredCatchParameter) { + var _ignoredCatchParameter = void 0; // Should error since we downlevel emit this variable. + } } diff --git a/tests/baselines/reference/invalidTryStatements2.errors.txt b/tests/baselines/reference/invalidTryStatements2.errors.txt index f2e88cfdc22a6..e1d285b8c8806 100644 --- a/tests/baselines/reference/invalidTryStatements2.errors.txt +++ b/tests/baselines/reference/invalidTryStatements2.errors.txt @@ -1,4 +1,3 @@ -tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts(3,13): error TS1005: '(' expected. tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts(6,5): error TS1005: 'try' expected. tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts(12,5): error TS1005: 'try' expected. tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts(13,5): error TS1005: 'try' expected. @@ -6,12 +5,10 @@ tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts(22,5): tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts(26,5): error TS1005: 'try' expected. -==== tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts (6 errors) ==== +==== tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts (5 errors) ==== function fn() { try { } catch { // syntax error, missing '(x)' - ~ -!!! error TS1005: '(' expected. } catch(x) { } // error missing try diff --git a/tests/baselines/reference/invalidTryStatements2.js b/tests/baselines/reference/invalidTryStatements2.js index 118b607817ad4..44fb6bb707115 100644 --- a/tests/baselines/reference/invalidTryStatements2.js +++ b/tests/baselines/reference/invalidTryStatements2.js @@ -32,7 +32,7 @@ function fn2() { function fn() { try { } - catch () { + catch (_ignoredCatchParameter) { } try { } diff --git a/tests/baselines/reference/tryStatements.js b/tests/baselines/reference/tryStatements.js index 723014c1b5259..da126cbcc6c48 100644 --- a/tests/baselines/reference/tryStatements.js +++ b/tests/baselines/reference/tryStatements.js @@ -1,20 +1,19 @@ //// [tryStatements.ts] function fn() { - try { + try { } catch { } - } catch (x) { - var x: any; - } + try { } catch (x) { var x: any; } try { } finally { } - try { }catch(z){ } finally { } + try { } catch(z) { } finally { } } //// [tryStatements.js] function fn() { - try { - } + try { } + catch (_ignoredCatchParameter) { } + try { } catch (x) { var x; } diff --git a/tests/baselines/reference/tryStatements.symbols b/tests/baselines/reference/tryStatements.symbols index 945ca2d9d8894..cc0147726659d 100644 --- a/tests/baselines/reference/tryStatements.symbols +++ b/tests/baselines/reference/tryStatements.symbols @@ -2,17 +2,14 @@ function fn() { >fn : Symbol(fn, Decl(tryStatements.ts, 0, 0)) - try { + try { } catch { } - } catch (x) { ->x : Symbol(x, Decl(tryStatements.ts, 3, 13)) - - var x: any; ->x : Symbol(x, Decl(tryStatements.ts, 4, 11)) - } + try { } catch (x) { var x: any; } +>x : Symbol(x, Decl(tryStatements.ts, 3, 19)) +>x : Symbol(x, Decl(tryStatements.ts, 3, 27)) try { } finally { } - try { }catch(z){ } finally { } ->z : Symbol(z, Decl(tryStatements.ts, 9, 17)) + try { } catch(z) { } finally { } +>z : Symbol(z, Decl(tryStatements.ts, 7, 18)) } diff --git a/tests/baselines/reference/tryStatements.types b/tests/baselines/reference/tryStatements.types index 07bc3997d8316..49e89dd79c020 100644 --- a/tests/baselines/reference/tryStatements.types +++ b/tests/baselines/reference/tryStatements.types @@ -2,17 +2,14 @@ function fn() { >fn : () => void - try { + try { } catch { } - } catch (x) { + try { } catch (x) { var x: any; } >x : any - - var x: any; >x : any - } try { } finally { } - try { }catch(z){ } finally { } + try { } catch(z) { } finally { } >z : any } From c65e5a1d137a99de621a91ed9a2507beb8a6477f Mon Sep 17 00:00:00 2001 From: Tingan Ho Date: Sun, 30 Jul 2017 11:03:43 +0200 Subject: [PATCH 07/17] Removes valid test cases from invalid test case file --- src/compiler/types.ts | 2 +- .../reference/invalidTryStatements2.errors.txt | 12 ++++-------- tests/baselines/reference/invalidTryStatements2.js | 8 -------- .../tryStatements/invalidTryStatements2.ts | 4 ---- 4 files changed, 5 insertions(+), 21 deletions(-) diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 5210b89eb1fbc..c97020c1142de 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; + parent?: TryStatement; // We parse missing try statements variableDeclaration?: VariableDeclaration; block: Block; } diff --git a/tests/baselines/reference/invalidTryStatements2.errors.txt b/tests/baselines/reference/invalidTryStatements2.errors.txt index e1d285b8c8806..38c30fb32ab17 100644 --- a/tests/baselines/reference/invalidTryStatements2.errors.txt +++ b/tests/baselines/reference/invalidTryStatements2.errors.txt @@ -1,16 +1,12 @@ -tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts(6,5): error TS1005: 'try' expected. -tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts(12,5): error TS1005: 'try' expected. -tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts(13,5): error TS1005: 'try' expected. +tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts(2,5): error TS1005: 'try' expected. +tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts(8,5): error TS1005: 'try' expected. +tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts(9,5): error TS1005: 'try' expected. +tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts(18,5): error TS1005: 'try' expected. tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts(22,5): error TS1005: 'try' expected. -tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts(26,5): error TS1005: 'try' expected. ==== tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts (5 errors) ==== function fn() { - try { - } catch { // syntax error, missing '(x)' - } - catch(x) { } // error missing try ~~~~~ !!! error TS1005: 'try' expected. diff --git a/tests/baselines/reference/invalidTryStatements2.js b/tests/baselines/reference/invalidTryStatements2.js index 44fb6bb707115..45b150b4094d7 100644 --- a/tests/baselines/reference/invalidTryStatements2.js +++ b/tests/baselines/reference/invalidTryStatements2.js @@ -1,9 +1,5 @@ //// [invalidTryStatements2.ts] function fn() { - try { - } catch { // syntax error, missing '(x)' - } - catch(x) { } // error missing try finally{ } // potential error; can be absorbed by the 'catch' @@ -30,10 +26,6 @@ function fn2() { //// [invalidTryStatements2.js] function fn() { - try { - } - catch (_ignoredCatchParameter) { - } try { } catch (x) { } // error missing try diff --git a/tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts b/tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts index 6937e509845ac..205d6f3f193f4 100644 --- a/tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts +++ b/tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts @@ -1,8 +1,4 @@ function fn() { - try { - } catch { // syntax error, missing '(x)' - } - catch(x) { } // error missing try finally{ } // potential error; can be absorbed by the 'catch' From de38ef74a4bfe79656a21a6d78f2a7802d2e8324 Mon Sep 17 00:00:00 2001 From: Tingan Ho Date: Sun, 30 Jul 2017 11:06:11 +0200 Subject: [PATCH 08/17] remove debugger --- src/compiler/checker.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 8c7e7abef1c56..6d07025a41fe8 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -20887,7 +20887,6 @@ namespace ts { } else if (/* !catchClause.variableDeclaration && */ languageVersion < ScriptTarget.ESNext) { const blockLocals = catchClause.block.locals; - debugger; if (blockLocals) { forEachKey(blockLocals, caughtName => { if (caughtName === "_ignoredCatchParameter") { From 58c8a2c03dcbfda2430039a623c0a13ae1425ea4 Mon Sep 17 00:00:00 2001 From: Tingan Ho Date: Sun, 30 Jul 2017 11:32:17 +0200 Subject: [PATCH 09/17] adds test for try-catch-finally --- tests/baselines/reference/tryStatements.js | 5 +++++ tests/baselines/reference/tryStatements.symbols | 4 +++- tests/baselines/reference/tryStatements.types | 2 ++ .../conformance/statements/tryStatements/tryStatements.ts | 2 ++ 4 files changed, 12 insertions(+), 1 deletion(-) diff --git a/tests/baselines/reference/tryStatements.js b/tests/baselines/reference/tryStatements.js index da126cbcc6c48..d99d0f91b35ea 100644 --- a/tests/baselines/reference/tryStatements.js +++ b/tests/baselines/reference/tryStatements.js @@ -6,6 +6,8 @@ function fn() { try { } finally { } + try { } catch { } finally { } + try { } catch(z) { } finally { } } @@ -20,6 +22,9 @@ function fn() { try { } finally { } try { } + catch (_ignoredCatchParameter) { } + finally { } + try { } catch (z) { } finally { } } diff --git a/tests/baselines/reference/tryStatements.symbols b/tests/baselines/reference/tryStatements.symbols index cc0147726659d..5bcb897d1931e 100644 --- a/tests/baselines/reference/tryStatements.symbols +++ b/tests/baselines/reference/tryStatements.symbols @@ -10,6 +10,8 @@ function fn() { try { } finally { } + try { } catch { } finally { } + try { } catch(z) { } finally { } ->z : Symbol(z, Decl(tryStatements.ts, 7, 18)) +>z : Symbol(z, Decl(tryStatements.ts, 9, 18)) } diff --git a/tests/baselines/reference/tryStatements.types b/tests/baselines/reference/tryStatements.types index 49e89dd79c020..cdc0a7c981d0d 100644 --- a/tests/baselines/reference/tryStatements.types +++ b/tests/baselines/reference/tryStatements.types @@ -10,6 +10,8 @@ function fn() { try { } finally { } + try { } catch { } finally { } + try { } catch(z) { } finally { } >z : any } diff --git a/tests/cases/conformance/statements/tryStatements/tryStatements.ts b/tests/cases/conformance/statements/tryStatements/tryStatements.ts index 42f549e6911ad..3fb395ca0ea06 100644 --- a/tests/cases/conformance/statements/tryStatements/tryStatements.ts +++ b/tests/cases/conformance/statements/tryStatements/tryStatements.ts @@ -6,5 +6,7 @@ function fn() { try { } finally { } + try { } catch { } finally { } + try { } catch(z) { } finally { } } \ No newline at end of file From 81fb3f702a9322139d433570d01f1dcde9abb729 Mon Sep 17 00:00:00 2001 From: Tingan Ho Date: Tue, 1 Aug 2017 22:10:12 +0200 Subject: [PATCH 10/17] Addresses CR feedback --- src/compiler/binder.ts | 2 +- src/compiler/checker.ts | 11 ----------- src/compiler/diagnosticMessages.json | 4 ---- src/compiler/transformers/es2015.ts | 3 ++- src/compiler/transformers/esnext.ts | 2 +- src/compiler/types.ts | 2 +- .../statements/tryStatements/invalidTryStatements.ts | 5 ----- 7 files changed, 5 insertions(+), 24 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index aa42d1b251bcc..45880f855fd7e 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -2924,7 +2924,7 @@ namespace ts { if (!node.variableDeclaration) { transformFlags |= TransformFlags.AssertESNext; } - else if (/* node.variableDeclaration && */ isBindingPattern(node.variableDeclaration.name)) { + else if (isBindingPattern(node.variableDeclaration.name)) { transformFlags |= TransformFlags.AssertES2015; } diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 6d07025a41fe8..f3979d8044181 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -20885,17 +20885,6 @@ namespace ts { } } } - else if (/* !catchClause.variableDeclaration && */ languageVersion < ScriptTarget.ESNext) { - const blockLocals = catchClause.block.locals; - if (blockLocals) { - forEachKey(blockLocals, caughtName => { - if (caughtName === "_ignoredCatchParameter") { - const localSymbol = blockLocals.get(caughtName); - grammarErrorOnNode(localSymbol.valueDeclaration, Diagnostics.Duplicate_identifier_ignoredCatchParameter_Compiler_uses_the_parameter_declaration_ignoredCatchParameter_to_bind_ignored_catched_exceptions); - } - }); - } - } checkBlock(catchClause.block); } diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index fbd91f33905f9..3b4b0ddf66711 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -2196,10 +2196,6 @@ "category": "Error", "code": 2713 }, - "Duplicate identifier '_ignoredCatchParameter'. Compiler uses the parameter declaration '_ignoredCatchParameter' to bind ignored catched exceptions.": { - "category": "Error", - "code": 2714 - }, "Import declaration '{0}' is using private name '{1}'.": { "category": "Error", diff --git a/src/compiler/transformers/es2015.ts b/src/compiler/transformers/es2015.ts index ebfd0b0069f97..41e68baa523f1 100644 --- a/src/compiler/transformers/es2015.ts +++ b/src/compiler/transformers/es2015.ts @@ -3173,7 +3173,8 @@ namespace ts { function visitCatchClause(node: CatchClause): CatchClause { const ancestorFacts = enterSubtree(HierarchyFacts.BlockScopeExcludes, HierarchyFacts.BlockScopeIncludes); let updated: CatchClause; - if (node.variableDeclaration && isBindingPattern(node.variableDeclaration.name)) { + Debug.assert(!!node.variableDeclaration, "Catch clauses should always be present when downleveling ES2015 code."); + if (isBindingPattern(node.variableDeclaration.name)) { const temp = createTempVariable(/*recordTempVariable*/ undefined); const newVariableDeclaration = createVariableDeclaration(temp); setTextRange(newVariableDeclaration, node.variableDeclaration); diff --git a/src/compiler/transformers/esnext.ts b/src/compiler/transformers/esnext.ts index 597b9d55b1648..11e79ae9eebed 100644 --- a/src/compiler/transformers/esnext.ts +++ b/src/compiler/transformers/esnext.ts @@ -216,7 +216,7 @@ namespace ts { function visitCatchClause(node: CatchClause): CatchClause { if (!node.variableDeclaration) { - return updateCatchClause(node, createVariableDeclaration("_ignoredCatchParameter"), node.block); + return updateCatchClause(node, createVariableDeclaration(createTempVariable(/*recordTempVariable*/ undefined)), node.block); } return visitEachChild(node, visitor, context); } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index c97020c1142de..9cf8e6fdf0017 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 parse missing try statements + parent?: TryStatement; // We make this optional to parse missing try statements variableDeclaration?: VariableDeclaration; block: Block; } diff --git a/tests/cases/conformance/statements/tryStatements/invalidTryStatements.ts b/tests/cases/conformance/statements/tryStatements/invalidTryStatements.ts index 6ecdfe1065609..c838cf45f6948 100644 --- a/tests/cases/conformance/statements/tryStatements/invalidTryStatements.ts +++ b/tests/cases/conformance/statements/tryStatements/invalidTryStatements.ts @@ -8,10 +8,5 @@ function fn() { try { } catch (z: any) { } try { } catch (a: number) { } try { } catch (y: string) { } - - - try { } catch { - let _ignoredCatchParameter; // Should error since we downlevel emit this variable. - } } From dbdbb05c66d3255e0b13a94a24c5ccb46a71ad08 Mon Sep 17 00:00:00 2001 From: Tingan Ho Date: Tue, 1 Aug 2017 22:23:34 +0200 Subject: [PATCH 11/17] Accept baselines --- .../constructorWithIncompleteTypeAnnotation.js | 2 +- .../reference/invalidTryStatements.errors.txt | 10 +--------- tests/baselines/reference/invalidTryStatements.js | 9 --------- tests/baselines/reference/tryStatements.js | 4 ++-- 4 files changed, 4 insertions(+), 21 deletions(-) diff --git a/tests/baselines/reference/constructorWithIncompleteTypeAnnotation.js b/tests/baselines/reference/constructorWithIncompleteTypeAnnotation.js index 013692a488949..f33c4b6d3161e 100644 --- a/tests/baselines/reference/constructorWithIncompleteTypeAnnotation.js +++ b/tests/baselines/reference/constructorWithIncompleteTypeAnnotation.js @@ -441,7 +441,7 @@ var BasicFeatures = (function () { var xx = c; retVal += ; try { } - catch (_ignoredCatchParameter) { } + catch (_a) { } Property; retVal += c.Member(); retVal += xx.Foo() ? 0 : 1; diff --git a/tests/baselines/reference/invalidTryStatements.errors.txt b/tests/baselines/reference/invalidTryStatements.errors.txt index 08dc5f1dfa0d0..a2f8a7bac0c96 100644 --- a/tests/baselines/reference/invalidTryStatements.errors.txt +++ b/tests/baselines/reference/invalidTryStatements.errors.txt @@ -1,10 +1,9 @@ tests/cases/conformance/statements/tryStatements/invalidTryStatements.ts(8,23): error TS1196: Catch clause variable cannot have a type annotation. tests/cases/conformance/statements/tryStatements/invalidTryStatements.ts(9,23): error TS1196: Catch clause variable cannot have a type annotation. tests/cases/conformance/statements/tryStatements/invalidTryStatements.ts(10,23): error TS1196: Catch clause variable cannot have a type annotation. -tests/cases/conformance/statements/tryStatements/invalidTryStatements.ts(14,13): error TS2714: Duplicate identifier '_ignoredCatchParameter'. Compiler uses the parameter declaration '_ignoredCatchParameter' to bind ignored catched exceptions. -==== tests/cases/conformance/statements/tryStatements/invalidTryStatements.ts (4 errors) ==== +==== tests/cases/conformance/statements/tryStatements/invalidTryStatements.ts (3 errors) ==== function fn() { try { } catch (x) { @@ -21,13 +20,6 @@ tests/cases/conformance/statements/tryStatements/invalidTryStatements.ts(14,13): try { } catch (y: string) { } ~~~~~~ !!! error TS1196: Catch clause variable cannot have a type annotation. - - - try { } catch { - let _ignoredCatchParameter; // Should error since we downlevel emit this variable. - ~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2714: Duplicate identifier '_ignoredCatchParameter'. Compiler uses the parameter declaration '_ignoredCatchParameter' to bind ignored catched exceptions. - } } \ No newline at end of file diff --git a/tests/baselines/reference/invalidTryStatements.js b/tests/baselines/reference/invalidTryStatements.js index 1436c83ae07dc..343ad6e058400 100644 --- a/tests/baselines/reference/invalidTryStatements.js +++ b/tests/baselines/reference/invalidTryStatements.js @@ -9,11 +9,6 @@ function fn() { try { } catch (z: any) { } try { } catch (a: number) { } try { } catch (y: string) { } - - - try { } catch { - let _ignoredCatchParameter; // Should error since we downlevel emit this variable. - } } @@ -32,8 +27,4 @@ function fn() { catch (a) { } try { } catch (y) { } - try { } - catch (_ignoredCatchParameter) { - var _ignoredCatchParameter = void 0; // Should error since we downlevel emit this variable. - } } diff --git a/tests/baselines/reference/tryStatements.js b/tests/baselines/reference/tryStatements.js index d99d0f91b35ea..fa5c9b5c92b3d 100644 --- a/tests/baselines/reference/tryStatements.js +++ b/tests/baselines/reference/tryStatements.js @@ -14,7 +14,7 @@ function fn() { //// [tryStatements.js] function fn() { try { } - catch (_ignoredCatchParameter) { } + catch (_a) { } try { } catch (x) { var x; @@ -22,7 +22,7 @@ function fn() { try { } finally { } try { } - catch (_ignoredCatchParameter) { } + catch (_b) { } finally { } try { } catch (z) { } From 192628510fc2494e8843ccc4d797d7b1a168f1d5 Mon Sep 17 00:00:00 2001 From: Tingan Ho Date: Wed, 2 Aug 2017 12:05:10 +0200 Subject: [PATCH 12/17] Fixes CR comments --- src/compiler/transformers/es2015.ts | 2 +- src/compiler/transformers/esnext.ts | 6 +++++- .../reference/emitter.ignoredCatchParameter.esnext.js | 11 ----------- .../emitter.ignoredCatchParameter.esnext.symbols | 7 ------- .../emitter.ignoredCatchParameter.esnext.types | 7 ------- .../noCatchBinding/emitter.noCatchBinding.esnext.ts | 8 ++++++++ .../statements/tryStatements/tryStatements.ts | 9 ++++++++- 7 files changed, 22 insertions(+), 28 deletions(-) delete mode 100644 tests/baselines/reference/emitter.ignoredCatchParameter.esnext.js delete mode 100644 tests/baselines/reference/emitter.ignoredCatchParameter.esnext.symbols delete mode 100644 tests/baselines/reference/emitter.ignoredCatchParameter.esnext.types create mode 100644 tests/cases/conformance/emitter/esnext/noCatchBinding/emitter.noCatchBinding.esnext.ts diff --git a/src/compiler/transformers/es2015.ts b/src/compiler/transformers/es2015.ts index 41e68baa523f1..5173352469935 100644 --- a/src/compiler/transformers/es2015.ts +++ b/src/compiler/transformers/es2015.ts @@ -2491,7 +2491,7 @@ namespace ts { const catchVariable = getGeneratedNameForNode(errorRecord); const returnMethod = createTempVariable(/*recordTempVariable*/ undefined); const values = createValuesHelper(context, expression, node.expression); - const next = createCall(createPropertyAccess(iterator, "next" ), /*typeArguments*/ undefined, []); + const next = createCall(createPropertyAccess(iterator, "next"), /*typeArguments*/ undefined, []); hoistVariableDeclaration(errorRecord); hoistVariableDeclaration(returnMethod); diff --git a/src/compiler/transformers/esnext.ts b/src/compiler/transformers/esnext.ts index 11e79ae9eebed..8d71016b0519c 100644 --- a/src/compiler/transformers/esnext.ts +++ b/src/compiler/transformers/esnext.ts @@ -216,7 +216,11 @@ namespace ts { function visitCatchClause(node: CatchClause): CatchClause { if (!node.variableDeclaration) { - return updateCatchClause(node, createVariableDeclaration(createTempVariable(/*recordTempVariable*/ undefined)), node.block); + return updateCatchClause( + node, + createVariableDeclaration(createTempVariable(/*recordTempVariable*/ undefined)), + visitNode(node.block, visitor, isBlock) + ); } return visitEachChild(node, visitor, context); } diff --git a/tests/baselines/reference/emitter.ignoredCatchParameter.esnext.js b/tests/baselines/reference/emitter.ignoredCatchParameter.esnext.js deleted file mode 100644 index 0f9254fd3cbaf..0000000000000 --- a/tests/baselines/reference/emitter.ignoredCatchParameter.esnext.js +++ /dev/null @@ -1,11 +0,0 @@ -//// [emitter.ignoredCatchParameter.esnext.ts] -function fn() { - try {} catch {} -} - - -//// [emitter.ignoredCatchParameter.esnext.js] -function fn() { - try { } - catch { } -} diff --git a/tests/baselines/reference/emitter.ignoredCatchParameter.esnext.symbols b/tests/baselines/reference/emitter.ignoredCatchParameter.esnext.symbols deleted file mode 100644 index 78838a33011ac..0000000000000 --- a/tests/baselines/reference/emitter.ignoredCatchParameter.esnext.symbols +++ /dev/null @@ -1,7 +0,0 @@ -=== tests/cases/conformance/emitter/esnext/noCatchParameter/emitter.ignoredCatchParameter.esnext.ts === -function fn() { ->fn : Symbol(fn, Decl(emitter.ignoredCatchParameter.esnext.ts, 0, 0)) - - try {} catch {} -} - diff --git a/tests/baselines/reference/emitter.ignoredCatchParameter.esnext.types b/tests/baselines/reference/emitter.ignoredCatchParameter.esnext.types deleted file mode 100644 index 06bf4ab268274..0000000000000 --- a/tests/baselines/reference/emitter.ignoredCatchParameter.esnext.types +++ /dev/null @@ -1,7 +0,0 @@ -=== tests/cases/conformance/emitter/esnext/noCatchParameter/emitter.ignoredCatchParameter.esnext.ts === -function fn() { ->fn : () => void - - try {} catch {} -} - diff --git a/tests/cases/conformance/emitter/esnext/noCatchBinding/emitter.noCatchBinding.esnext.ts b/tests/cases/conformance/emitter/esnext/noCatchBinding/emitter.noCatchBinding.esnext.ts new file mode 100644 index 0000000000000..8e87b3c8c8fc6 --- /dev/null +++ b/tests/cases/conformance/emitter/esnext/noCatchBinding/emitter.noCatchBinding.esnext.ts @@ -0,0 +1,8 @@ +// @target: esnext +function f() { + try { } catch { } + try { } catch { + try { } catch { } + } + try { } catch { } finally { } +} \ No newline at end of file diff --git a/tests/cases/conformance/statements/tryStatements/tryStatements.ts b/tests/cases/conformance/statements/tryStatements/tryStatements.ts index 3fb395ca0ea06..0a47ba7a94bef 100644 --- a/tests/cases/conformance/statements/tryStatements/tryStatements.ts +++ b/tests/cases/conformance/statements/tryStatements/tryStatements.ts @@ -2,11 +2,18 @@ function fn() { try { } catch { } + try { } catch { + try { } catch { + try { } catch { } + } + try { } catch { } + } + try { } catch (x) { var x: any; } try { } finally { } try { } catch { } finally { } - try { } catch(z) { } finally { } + try { } catch (z) { } finally { } } \ No newline at end of file From 053b708bf136295af812a97fb93b1554285d60bf Mon Sep 17 00:00:00 2001 From: Tingan Ho Date: Wed, 2 Aug 2017 17:53:46 +0200 Subject: [PATCH 13/17] Accept baseline --- .../emitter.noCatchBinding.esnext.js | 22 +++++++++++++++++++ .../emitter.noCatchBinding.esnext.symbols | 10 +++++++++ .../emitter.noCatchBinding.esnext.types | 10 +++++++++ tests/baselines/reference/tryStatements.js | 21 ++++++++++++++++-- .../baselines/reference/tryStatements.symbols | 15 +++++++++---- tests/baselines/reference/tryStatements.types | 9 +++++++- 6 files changed, 80 insertions(+), 7 deletions(-) create mode 100644 tests/baselines/reference/emitter.noCatchBinding.esnext.js create mode 100644 tests/baselines/reference/emitter.noCatchBinding.esnext.symbols create mode 100644 tests/baselines/reference/emitter.noCatchBinding.esnext.types diff --git a/tests/baselines/reference/emitter.noCatchBinding.esnext.js b/tests/baselines/reference/emitter.noCatchBinding.esnext.js new file mode 100644 index 0000000000000..f47a947ca1a48 --- /dev/null +++ b/tests/baselines/reference/emitter.noCatchBinding.esnext.js @@ -0,0 +1,22 @@ +//// [emitter.noCatchBinding.esnext.ts] +function f() { + try { } catch { } + try { } catch { + try { } catch { } + } + try { } catch { } finally { } +} + +//// [emitter.noCatchBinding.esnext.js] +function f() { + try { } + catch { } + try { } + catch { + try { } + catch { } + } + try { } + catch { } + finally { } +} diff --git a/tests/baselines/reference/emitter.noCatchBinding.esnext.symbols b/tests/baselines/reference/emitter.noCatchBinding.esnext.symbols new file mode 100644 index 0000000000000..91242f5b01cee --- /dev/null +++ b/tests/baselines/reference/emitter.noCatchBinding.esnext.symbols @@ -0,0 +1,10 @@ +=== tests/cases/conformance/emitter/esnext/noCatchBinding/emitter.noCatchBinding.esnext.ts === +function f() { +>f : Symbol(f, Decl(emitter.noCatchBinding.esnext.ts, 0, 0)) + + try { } catch { } + try { } catch { + try { } catch { } + } + try { } catch { } finally { } +} diff --git a/tests/baselines/reference/emitter.noCatchBinding.esnext.types b/tests/baselines/reference/emitter.noCatchBinding.esnext.types new file mode 100644 index 0000000000000..70c2b728a5dc6 --- /dev/null +++ b/tests/baselines/reference/emitter.noCatchBinding.esnext.types @@ -0,0 +1,10 @@ +=== tests/cases/conformance/emitter/esnext/noCatchBinding/emitter.noCatchBinding.esnext.ts === +function f() { +>f : () => void + + try { } catch { } + try { } catch { + try { } catch { } + } + try { } catch { } finally { } +} diff --git a/tests/baselines/reference/tryStatements.js b/tests/baselines/reference/tryStatements.js index fa5c9b5c92b3d..64fe2cf06a763 100644 --- a/tests/baselines/reference/tryStatements.js +++ b/tests/baselines/reference/tryStatements.js @@ -2,13 +2,20 @@ function fn() { try { } catch { } + try { } catch { + try { } catch { + try { } catch { } + } + try { } catch { } + } + try { } catch (x) { var x: any; } try { } finally { } try { } catch { } finally { } - try { } catch(z) { } finally { } + try { } catch (z) { } finally { } } //// [tryStatements.js] @@ -16,13 +23,23 @@ function fn() { try { } catch (_a) { } try { } + catch (_b) { + try { } + catch (_c) { + try { } + catch (_d) { } + } + try { } + catch (_e) { } + } + try { } catch (x) { var x; } try { } finally { } try { } - catch (_b) { } + catch (_f) { } finally { } try { } catch (z) { } diff --git a/tests/baselines/reference/tryStatements.symbols b/tests/baselines/reference/tryStatements.symbols index 5bcb897d1931e..69e9918a98b42 100644 --- a/tests/baselines/reference/tryStatements.symbols +++ b/tests/baselines/reference/tryStatements.symbols @@ -4,14 +4,21 @@ function fn() { try { } catch { } + try { } catch { + try { } catch { + try { } catch { } + } + try { } catch { } + } + try { } catch (x) { var x: any; } ->x : Symbol(x, Decl(tryStatements.ts, 3, 19)) ->x : Symbol(x, Decl(tryStatements.ts, 3, 27)) +>x : Symbol(x, Decl(tryStatements.ts, 10, 19)) +>x : Symbol(x, Decl(tryStatements.ts, 10, 27)) try { } finally { } try { } catch { } finally { } - try { } catch(z) { } finally { } ->z : Symbol(z, Decl(tryStatements.ts, 9, 18)) + try { } catch (z) { } finally { } +>z : Symbol(z, Decl(tryStatements.ts, 16, 19)) } diff --git a/tests/baselines/reference/tryStatements.types b/tests/baselines/reference/tryStatements.types index cdc0a7c981d0d..05c0256813540 100644 --- a/tests/baselines/reference/tryStatements.types +++ b/tests/baselines/reference/tryStatements.types @@ -4,6 +4,13 @@ function fn() { try { } catch { } + try { } catch { + try { } catch { + try { } catch { } + } + try { } catch { } + } + try { } catch (x) { var x: any; } >x : any >x : any @@ -12,6 +19,6 @@ function fn() { try { } catch { } finally { } - try { } catch(z) { } finally { } + try { } catch (z) { } finally { } >z : any } From d5c24f3cd3bd0d5375a92ffc5a9b1620ed1d6571 Mon Sep 17 00:00:00 2001 From: Tingan Ho Date: Wed, 2 Aug 2017 20:13:43 +0200 Subject: [PATCH 14/17] Addresses CR comment --- src/compiler/emitter.ts | 2 +- src/compiler/factory.ts | 4 ++-- src/compiler/parser.ts | 4 ++++ src/compiler/transformers/es2015.ts | 2 +- src/compiler/types.ts | 2 +- 5 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 1c5194054cacd..24769afd5d45a 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 34727e4c41422..47df0a9bdc27a 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 12c516c88b03e..4547df15790df 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 5173352469935..2b0b175e2a56f 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 9cf8e6fdf0017..ca70a6fe20921 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; } From f9e85ec0917342727957f160acf43e3890f46762 Mon Sep 17 00:00:00 2001 From: Tingan Ho Date: Wed, 2 Aug 2017 20:48:31 +0200 Subject: [PATCH 15/17] Adds missing test cases --- .../invalidTryStatements2.errors.txt | 40 +++++++++--------- .../reference/invalidTryStatements2.js | 42 ++++++++----------- .../tryStatements/invalidTryStatements2.ts | 22 ++++------ 3 files changed, 48 insertions(+), 56 deletions(-) diff --git a/tests/baselines/reference/invalidTryStatements2.errors.txt b/tests/baselines/reference/invalidTryStatements2.errors.txt index 38c30fb32ab17..d43c33e55a31d 100644 --- a/tests/baselines/reference/invalidTryStatements2.errors.txt +++ b/tests/baselines/reference/invalidTryStatements2.errors.txt @@ -1,17 +1,23 @@ tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts(2,5): error TS1005: 'try' expected. -tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts(8,5): error TS1005: 'try' expected. -tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts(9,5): error TS1005: 'try' expected. -tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts(18,5): error TS1005: 'try' expected. -tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts(22,5): error TS1005: 'try' expected. +tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts(6,12): error TS1005: 'finally' expected. +tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts(10,5): error TS1005: 'try' expected. +tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts(11,5): error TS1005: 'try' expected. +tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts(15,5): error TS1005: 'try' expected. +tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts(17,5): error TS1005: 'try' expected. +tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts(19,20): error TS1003: Identifier expected. -==== tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts (5 errors) ==== +==== tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts (7 errors) ==== function fn() { catch(x) { } // error missing try ~~~~~ !!! error TS1005: 'try' expected. - finally{ } // potential error; can be absorbed by the 'catch' + finally { } // potential error; can be absorbed by the 'catch' + + try { }; // missing finally + ~ +!!! error TS1005: 'finally' expected. } function fn2() { @@ -21,22 +27,18 @@ tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts(22,5): catch (x) { } // error missing try ~~~~~ !!! error TS1005: 'try' expected. + + try { } finally { } // statement is here, so the 'catch' clause above doesn't absorb errors from the 'finally' clause below - // no error - try { - } - finally { - } - - // error missing try - finally { + finally { } // error missing try ~~~~~~~ !!! error TS1005: 'try' expected. - } - - // error missing try - catch (x) { + + catch (x) { } // error missing try ~~~~~ !!! error TS1005: 'try' expected. - } + + try { } catch () { } // error missing catch binding + ~ +!!! error TS1003: Identifier expected. } \ No newline at end of file diff --git a/tests/baselines/reference/invalidTryStatements2.js b/tests/baselines/reference/invalidTryStatements2.js index 45b150b4094d7..25d411ca484c3 100644 --- a/tests/baselines/reference/invalidTryStatements2.js +++ b/tests/baselines/reference/invalidTryStatements2.js @@ -2,26 +2,22 @@ function fn() { catch(x) { } // error missing try - finally{ } // potential error; can be absorbed by the 'catch' + finally { } // potential error; can be absorbed by the 'catch' + + try { }; // missing finally } function fn2() { finally { } // error missing try catch (x) { } // error missing try + + try { } finally { } // statement is here, so the 'catch' clause above doesn't absorb errors from the 'finally' clause below - // no error - try { - } - finally { - } - - // error missing try - finally { - } + finally { } // error missing try + + catch (x) { } // error missing try - // error missing try - catch (x) { - } + try { } catch () { } // error missing catch binding } //// [invalidTryStatements2.js] @@ -30,6 +26,9 @@ function fn() { } catch (x) { } // error missing try finally { } // potential error; can be absorbed by the 'catch' + try { } + finally { } + ; // missing finally } function fn2() { try { @@ -38,19 +37,14 @@ function fn2() { try { } catch (x) { } // error missing try - // no error + try { } + finally { } // statement is here, so the 'catch' clause above doesn't absorb errors from the 'finally' clause below try { } - finally { - } - // error missing try - try { - } - finally { - } - // error missing try + finally { } // error missing try try { } - catch (x) { - } + catch (x) { } // error missing try + try { } + catch () { } // error missing catch binding } diff --git a/tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts b/tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts index 205d6f3f193f4..d3d261830f4aa 100644 --- a/tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts +++ b/tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts @@ -1,24 +1,20 @@ function fn() { catch(x) { } // error missing try - finally{ } // potential error; can be absorbed by the 'catch' + finally { } // potential error; can be absorbed by the 'catch' + + try { }; // missing finally } function fn2() { finally { } // error missing try catch (x) { } // error missing try + + try { } finally { } // statement is here, so the 'catch' clause above doesn't absorb errors from the 'finally' clause below - // no error - try { - } - finally { - } - - // error missing try - finally { - } + finally { } // error missing try + + catch (x) { } // error missing try - // error missing try - catch (x) { - } + try { } catch () { } // error missing catch binding } \ No newline at end of file From 4f3e13ab8c290fe8a29d661fec280ff700f68021 Mon Sep 17 00:00:00 2001 From: Tingan Ho Date: Wed, 2 Aug 2017 20:50:45 +0200 Subject: [PATCH 16/17] Typo --- tests/baselines/reference/invalidTryStatements2.errors.txt | 2 +- tests/baselines/reference/invalidTryStatements2.js | 4 ++-- .../statements/tryStatements/invalidTryStatements2.ts | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/baselines/reference/invalidTryStatements2.errors.txt b/tests/baselines/reference/invalidTryStatements2.errors.txt index d43c33e55a31d..a7c436236f2e4 100644 --- a/tests/baselines/reference/invalidTryStatements2.errors.txt +++ b/tests/baselines/reference/invalidTryStatements2.errors.txt @@ -15,7 +15,7 @@ tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts(19,20) finally { } // potential error; can be absorbed by the 'catch' - try { }; // missing finally + try { }; // error missing finally ~ !!! error TS1005: 'finally' expected. } diff --git a/tests/baselines/reference/invalidTryStatements2.js b/tests/baselines/reference/invalidTryStatements2.js index 25d411ca484c3..50aff00c51555 100644 --- a/tests/baselines/reference/invalidTryStatements2.js +++ b/tests/baselines/reference/invalidTryStatements2.js @@ -4,7 +4,7 @@ function fn() { finally { } // potential error; can be absorbed by the 'catch' - try { }; // missing finally + try { }; // error missing finally } function fn2() { @@ -28,7 +28,7 @@ function fn() { finally { } // potential error; can be absorbed by the 'catch' try { } finally { } - ; // missing finally + ; // error missing finally } function fn2() { try { diff --git a/tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts b/tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts index d3d261830f4aa..7fb1b135c906b 100644 --- a/tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts +++ b/tests/cases/conformance/statements/tryStatements/invalidTryStatements2.ts @@ -3,7 +3,7 @@ function fn() { finally { } // potential error; can be absorbed by the 'catch' - try { }; // missing finally + try { }; // error missing finally } function fn2() { From 3da1a53d7ec22a78346e373c9d5f887538a800d8 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Wed, 2 Aug 2017 12:50:04 -0700 Subject: [PATCH 17/17] Amend comment about explicitly setting catch clause variables to 'undefined'. --- src/compiler/parser.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 4547df15790df..155ad3999bfa3 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -4784,7 +4784,7 @@ namespace ts { parseExpected(SyntaxKind.CloseParenToken); } else { - // Keep shape of node to not avoid degrading performance. + // Keep shape of node to avoid degrading performance. result.variableDeclaration = undefined; }