mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-05 16:38:05 -06:00
fix(42678): detect access to uninitialized variable in IIFE (#42776)
* fix(42678): detect access to uninitialized variable in IIFE * improve performance * Add missing space to match coding guidelines * simplify the implementation Co-authored-by: Jake Bailey <5341706+jakebailey@users.noreply.github.com>
This commit is contained in:
parent
1f275d705d
commit
7a1687de26
@ -2536,10 +2536,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 {
|
||||
|
||||
@ -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.
|
||||
}
|
||||
|
||||
@ -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];
|
||||
}
|
||||
|
||||
@ -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))
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
|
||||
@ -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.
|
||||
})();
|
||||
|
||||
@ -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)();
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user