diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 2e0f1ef628101..42ca22e26e588 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2533,10 +2533,12 @@ namespace ts { /* Starting from 'initial' node walk up the parent chain until 'stopAt' node is reached. * If at any point current node is equal to 'parent' node - return true. + * If current node is an IIFE, continue walking up. * Return false if 'stopAt' node is reached or isFunctionLike(current) === true. */ function isSameScopeDescendentOf(initial: Node, parent: Node | undefined, stopAt: Node): boolean { - return !!parent && !!findAncestor(initial, n => n === stopAt || isFunctionLike(n) ? "quit" : n === parent); + return !!parent && !!findAncestor(initial, n => n === parent + || (n === stopAt || isFunctionLike(n) && !getImmediatelyInvokedFunctionExpression(n) ? "quit" : false)); } function getAnyImportSyntax(node: Node): AnyImportSyntax | undefined { diff --git a/tests/baselines/reference/blockScopedVariablesUseBeforeDef.errors.txt b/tests/baselines/reference/blockScopedVariablesUseBeforeDef.errors.txt index 91bd5dde00cb6..9dacd0975bd53 100644 --- a/tests/baselines/reference/blockScopedVariablesUseBeforeDef.errors.txt +++ b/tests/baselines/reference/blockScopedVariablesUseBeforeDef.errors.txt @@ -2,9 +2,12 @@ tests/cases/compiler/blockScopedVariablesUseBeforeDef.ts(2,13): error TS2448: Bl tests/cases/compiler/blockScopedVariablesUseBeforeDef.ts(58,20): error TS2448: Block-scoped variable 'x' used before its declaration. tests/cases/compiler/blockScopedVariablesUseBeforeDef.ts(65,20): error TS2448: Block-scoped variable 'x' used before its declaration. tests/cases/compiler/blockScopedVariablesUseBeforeDef.ts(100,12): error TS2448: Block-scoped variable 'x' used before its declaration. +tests/cases/compiler/blockScopedVariablesUseBeforeDef.ts(111,28): error TS2448: Block-scoped variable 'a' used before its declaration. +tests/cases/compiler/blockScopedVariablesUseBeforeDef.ts(112,21): error TS2448: Block-scoped variable 'a' used before its declaration. +tests/cases/compiler/blockScopedVariablesUseBeforeDef.ts(122,22): error TS2448: Block-scoped variable 'a' used before its declaration. -==== tests/cases/compiler/blockScopedVariablesUseBeforeDef.ts (4 errors) ==== +==== tests/cases/compiler/blockScopedVariablesUseBeforeDef.ts (7 errors) ==== function foo0() { let a = x; ~ @@ -120,4 +123,33 @@ tests/cases/compiler/blockScopedVariablesUseBeforeDef.ts(100,12): error TS2448: } let x } + + function foo15() { + // https://github.com/microsoft/TypeScript/issues/42678 + const [ + a, + b, + ] = ((): [number, number] => { + (() => console.log(a))(); // should error + ~ +!!! error TS2448: Block-scoped variable 'a' used before its declaration. +!!! related TS2728 tests/cases/compiler/blockScopedVariablesUseBeforeDef.ts:108:9: 'a' is declared here. + console.log(a); // should error + ~ +!!! error TS2448: Block-scoped variable 'a' used before its declaration. +!!! related TS2728 tests/cases/compiler/blockScopedVariablesUseBeforeDef.ts:108:9: 'a' is declared here. + const b = () => a; // should be ok + return [ + 0, + 0, + ]; + })(); + } + + function foo16() { + let [a] = (() => a)(); + ~ +!!! error TS2448: Block-scoped variable 'a' used before its declaration. +!!! related TS2728 tests/cases/compiler/blockScopedVariablesUseBeforeDef.ts:122:10: 'a' is declared here. + } \ No newline at end of file diff --git a/tests/baselines/reference/blockScopedVariablesUseBeforeDef.js b/tests/baselines/reference/blockScopedVariablesUseBeforeDef.js index 9ca3f8998a2eb..b49ce9ddaa4b2 100644 --- a/tests/baselines/reference/blockScopedVariablesUseBeforeDef.js +++ b/tests/baselines/reference/blockScopedVariablesUseBeforeDef.js @@ -102,6 +102,26 @@ function foo14() { } let x } + +function foo15() { + // https://github.com/microsoft/TypeScript/issues/42678 + const [ + a, + b, + ] = ((): [number, number] => { + (() => console.log(a))(); // should error + console.log(a); // should error + const b = () => a; // should be ok + return [ + 0, + 0, + ]; + })(); +} + +function foo16() { + let [a] = (() => a)(); +} //// [blockScopedVariablesUseBeforeDef.js] @@ -219,3 +239,18 @@ function foo14() { }; var x; } +function foo15() { + // https://github.com/microsoft/TypeScript/issues/42678 + var _a = (function () { + (function () { return console.log(a); })(); // should error + console.log(a); // should error + var b = function () { return a; }; // should be ok + return [ + 0, + 0, + ]; + })(), a = _a[0], b = _a[1]; +} +function foo16() { + var a = (function () { return a; })()[0]; +} diff --git a/tests/baselines/reference/blockScopedVariablesUseBeforeDef.symbols b/tests/baselines/reference/blockScopedVariablesUseBeforeDef.symbols index 83cb91db1d0cd..ea588cd22fa19 100644 --- a/tests/baselines/reference/blockScopedVariablesUseBeforeDef.symbols +++ b/tests/baselines/reference/blockScopedVariablesUseBeforeDef.symbols @@ -213,3 +213,46 @@ function foo14() { >x : Symbol(x, Decl(blockScopedVariablesUseBeforeDef.ts, 101, 7)) } +function foo15() { +>foo15 : Symbol(foo15, Decl(blockScopedVariablesUseBeforeDef.ts, 102, 1)) + + // https://github.com/microsoft/TypeScript/issues/42678 + const [ + a, +>a : Symbol(a, Decl(blockScopedVariablesUseBeforeDef.ts, 106, 11)) + + b, +>b : Symbol(b, Decl(blockScopedVariablesUseBeforeDef.ts, 107, 10)) + + ] = ((): [number, number] => { + (() => console.log(a))(); // should error +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>a : Symbol(a, Decl(blockScopedVariablesUseBeforeDef.ts, 106, 11)) + + console.log(a); // should error +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>a : Symbol(a, Decl(blockScopedVariablesUseBeforeDef.ts, 106, 11)) + + const b = () => a; // should be ok +>b : Symbol(b, Decl(blockScopedVariablesUseBeforeDef.ts, 112, 13)) +>a : Symbol(a, Decl(blockScopedVariablesUseBeforeDef.ts, 106, 11)) + + return [ + 0, + 0, + ]; + })(); +} + +function foo16() { +>foo16 : Symbol(foo16, Decl(blockScopedVariablesUseBeforeDef.ts, 118, 1)) + + let [a] = (() => a)(); +>a : Symbol(a, Decl(blockScopedVariablesUseBeforeDef.ts, 121, 9)) +>a : Symbol(a, Decl(blockScopedVariablesUseBeforeDef.ts, 121, 9)) +} + diff --git a/tests/baselines/reference/blockScopedVariablesUseBeforeDef.types b/tests/baselines/reference/blockScopedVariablesUseBeforeDef.types index 3098b8c0f91e0..e24197911cf04 100644 --- a/tests/baselines/reference/blockScopedVariablesUseBeforeDef.types +++ b/tests/baselines/reference/blockScopedVariablesUseBeforeDef.types @@ -225,3 +225,65 @@ function foo14() { >x : any } +function foo15() { +>foo15 : () => void + + // https://github.com/microsoft/TypeScript/issues/42678 + const [ + a, +>a : number + + b, +>b : number + + ] = ((): [number, number] => { +>((): [number, number] => { (() => console.log(a))(); // should error console.log(a); // should error const b = () => a; // should be ok return [ 0, 0, ]; })() : [number, number] +>((): [number, number] => { (() => console.log(a))(); // should error console.log(a); // should error const b = () => a; // should be ok return [ 0, 0, ]; }) : () => [number, number] +>(): [number, number] => { (() => console.log(a))(); // should error console.log(a); // should error const b = () => a; // should be ok return [ 0, 0, ]; } : () => [number, number] + + (() => console.log(a))(); // should error +>(() => console.log(a))() : void +>(() => console.log(a)) : () => void +>() => console.log(a) : () => void +>console.log(a) : void +>console.log : (...data: any[]) => void +>console : Console +>log : (...data: any[]) => void +>a : number + + console.log(a); // should error +>console.log(a) : void +>console.log : (...data: any[]) => void +>console : Console +>log : (...data: any[]) => void +>a : number + + const b = () => a; // should be ok +>b : () => number +>() => a : () => number +>a : number + + return [ +>[ 0, 0, ] : [number, number] + + 0, +>0 : 0 + + 0, +>0 : 0 + + ]; + })(); +} + +function foo16() { +>foo16 : () => void + + let [a] = (() => a)(); +>a : any +>(() => a)() : any +>(() => a) : () => any +>() => a : () => any +>a : any +} + diff --git a/tests/baselines/reference/tryCatchFinallyControlFlow.errors.txt b/tests/baselines/reference/tryCatchFinallyControlFlow.errors.txt index a6972d05d8ec5..79578f9144de1 100644 --- a/tests/baselines/reference/tryCatchFinallyControlFlow.errors.txt +++ b/tests/baselines/reference/tryCatchFinallyControlFlow.errors.txt @@ -2,10 +2,11 @@ tests/cases/compiler/tryCatchFinallyControlFlow.ts(105,5): error TS7027: Unreach tests/cases/compiler/tryCatchFinallyControlFlow.ts(118,9): error TS7027: Unreachable code detected. tests/cases/compiler/tryCatchFinallyControlFlow.ts(218,13): error TS7027: Unreachable code detected. tests/cases/compiler/tryCatchFinallyControlFlow.ts(220,9): error TS7027: Unreachable code detected. +tests/cases/compiler/tryCatchFinallyControlFlow.ts(255,9): error TS2448: Block-scoped variable 'x' used before its declaration. tests/cases/compiler/tryCatchFinallyControlFlow.ts(255,9): error TS7027: Unreachable code detected. -==== tests/cases/compiler/tryCatchFinallyControlFlow.ts (5 errors) ==== +==== tests/cases/compiler/tryCatchFinallyControlFlow.ts (6 errors) ==== // Repro from #34797 function f1() { @@ -270,6 +271,9 @@ tests/cases/compiler/tryCatchFinallyControlFlow.ts(255,9): error TS7027: Unreach return null; } x; // Unreachable + ~ +!!! error TS2448: Block-scoped variable 'x' used before its declaration. +!!! related TS2728 tests/cases/compiler/tryCatchFinallyControlFlow.ts:248:11: 'x' is declared here. ~~ !!! error TS7027: Unreachable code detected. })(); diff --git a/tests/cases/compiler/blockScopedVariablesUseBeforeDef.ts b/tests/cases/compiler/blockScopedVariablesUseBeforeDef.ts index 351bdde122e1c..2e0b0727895d0 100644 --- a/tests/cases/compiler/blockScopedVariablesUseBeforeDef.ts +++ b/tests/cases/compiler/blockScopedVariablesUseBeforeDef.ts @@ -102,3 +102,23 @@ function foo14() { } let x } + +function foo15() { + // https://github.com/microsoft/TypeScript/issues/42678 + const [ + a, + b, + ] = ((): [number, number] => { + (() => console.log(a))(); // should error + console.log(a); // should error + const b = () => a; // should be ok + return [ + 0, + 0, + ]; + })(); +} + +function foo16() { + let [a] = (() => a)(); +}