Skip to content

Commit 6017625

Browse files
authored
do not report use-before-declaration error in async IIFE initializer (#50199)
1 parent 46b015f commit 6017625

File tree

6 files changed

+150
-1
lines changed

6 files changed

+150
-1
lines changed

src/compiler/checker.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2648,7 +2648,7 @@ namespace ts {
26482648
*/
26492649
function isSameScopeDescendentOf(initial: Node, parent: Node | undefined, stopAt: Node): boolean {
26502650
return !!parent && !!findAncestor(initial, n => n === parent
2651-
|| (n === stopAt || isFunctionLike(n) && !getImmediatelyInvokedFunctionExpression(n) ? "quit" : false));
2651+
|| (n === stopAt || isFunctionLike(n) && (!getImmediatelyInvokedFunctionExpression(n) || isAsyncFunction(n)) ? "quit" : false));
26522652
}
26532653

26542654
function getAnyImportSyntax(node: Node): AnyImportSyntax | undefined {

tests/baselines/reference/blockScopedVariablesUseBeforeDef.errors.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,4 +152,16 @@ tests/cases/compiler/blockScopedVariablesUseBeforeDef.ts(122,22): error TS2448:
152152
!!! error TS2448: Block-scoped variable 'a' used before its declaration.
153153
!!! related TS2728 tests/cases/compiler/blockScopedVariablesUseBeforeDef.ts:122:10: 'a' is declared here.
154154
}
155+
156+
function foo17() {
157+
const promise = (async () => {
158+
promise
159+
foo
160+
await null
161+
promise
162+
foo
163+
})()
164+
165+
const foo = 1;
166+
}
155167

tests/baselines/reference/blockScopedVariablesUseBeforeDef.js

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,9 +122,57 @@ function foo15() {
122122
function foo16() {
123123
let [a] = (() => a)();
124124
}
125+
126+
function foo17() {
127+
const promise = (async () => {
128+
promise
129+
foo
130+
await null
131+
promise
132+
foo
133+
})()
134+
135+
const foo = 1;
136+
}
125137

126138

127139
//// [blockScopedVariablesUseBeforeDef.js]
140+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
141+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
142+
return new (P || (P = Promise))(function (resolve, reject) {
143+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
144+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
145+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
146+
step((generator = generator.apply(thisArg, _arguments || [])).next());
147+
});
148+
};
149+
var __generator = (this && this.__generator) || function (thisArg, body) {
150+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
151+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
152+
function verb(n) { return function (v) { return step([n, v]); }; }
153+
function step(op) {
154+
if (f) throw new TypeError("Generator is already executing.");
155+
while (_) try {
156+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
157+
if (y = 0, t) op = [op[0] & 2, t.value];
158+
switch (op[0]) {
159+
case 0: case 1: t = op; break;
160+
case 4: _.label++; return { value: op[1], done: false };
161+
case 5: _.label++; y = op[1]; op = [0]; continue;
162+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
163+
default:
164+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
165+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
166+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
167+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
168+
if (t[2]) _.ops.pop();
169+
_.trys.pop(); continue;
170+
}
171+
op = body.call(thisArg, _);
172+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
173+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
174+
}
175+
};
128176
function foo0() {
129177
var a = x;
130178
var x;
@@ -254,3 +302,22 @@ function foo15() {
254302
function foo16() {
255303
var a = (function () { return a; })()[0];
256304
}
305+
function foo17() {
306+
var _this = this;
307+
var promise = (function () { return __awaiter(_this, void 0, void 0, function () {
308+
return __generator(this, function (_a) {
309+
switch (_a.label) {
310+
case 0:
311+
promise;
312+
foo;
313+
return [4 /*yield*/, null];
314+
case 1:
315+
_a.sent();
316+
promise;
317+
foo;
318+
return [2 /*return*/];
319+
}
320+
});
321+
}); })();
322+
var foo = 1;
323+
}

tests/baselines/reference/blockScopedVariablesUseBeforeDef.symbols

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,3 +256,28 @@ function foo16() {
256256
>a : Symbol(a, Decl(blockScopedVariablesUseBeforeDef.ts, 121, 9))
257257
}
258258

259+
function foo17() {
260+
>foo17 : Symbol(foo17, Decl(blockScopedVariablesUseBeforeDef.ts, 122, 1))
261+
262+
const promise = (async () => {
263+
>promise : Symbol(promise, Decl(blockScopedVariablesUseBeforeDef.ts, 125, 9))
264+
265+
promise
266+
>promise : Symbol(promise, Decl(blockScopedVariablesUseBeforeDef.ts, 125, 9))
267+
268+
foo
269+
>foo : Symbol(foo, Decl(blockScopedVariablesUseBeforeDef.ts, 133, 9))
270+
271+
await null
272+
promise
273+
>promise : Symbol(promise, Decl(blockScopedVariablesUseBeforeDef.ts, 125, 9))
274+
275+
foo
276+
>foo : Symbol(foo, Decl(blockScopedVariablesUseBeforeDef.ts, 133, 9))
277+
278+
})()
279+
280+
const foo = 1;
281+
>foo : Symbol(foo, Decl(blockScopedVariablesUseBeforeDef.ts, 133, 9))
282+
}
283+

tests/baselines/reference/blockScopedVariablesUseBeforeDef.types

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,3 +287,35 @@ function foo16() {
287287
>a : any
288288
}
289289

290+
function foo17() {
291+
>foo17 : () => void
292+
293+
const promise = (async () => {
294+
>promise : Promise<void>
295+
>(async () => { promise foo await null promise foo })() : Promise<void>
296+
>(async () => { promise foo await null promise foo }) : () => Promise<void>
297+
>async () => { promise foo await null promise foo } : () => Promise<void>
298+
299+
promise
300+
>promise : Promise<void>
301+
302+
foo
303+
>foo : 1
304+
305+
await null
306+
>await null : null
307+
>null : null
308+
309+
promise
310+
>promise : Promise<void>
311+
312+
foo
313+
>foo : 1
314+
315+
})()
316+
317+
const foo = 1;
318+
>foo : 1
319+
>1 : 1
320+
}
321+

tests/cases/compiler/blockScopedVariablesUseBeforeDef.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// @target: ES5
2+
// @lib: esnext, dom
23
function foo0() {
34
let a = x;
45
let x;
@@ -122,3 +123,15 @@ function foo15() {
122123
function foo16() {
123124
let [a] = (() => a)();
124125
}
126+
127+
function foo17() {
128+
const promise = (async () => {
129+
promise
130+
foo
131+
await null
132+
promise
133+
foo
134+
})()
135+
136+
const foo = 1;
137+
}

0 commit comments

Comments
 (0)