Skip to content

Commit a8aa070

Browse files
authored
Merge pull request #14900 from Microsoft/Fix14892
Fix #14892: Add undefined check before using the intializer of for-statment
2 parents 294ac30 + 74dd1c0 commit a8aa070

10 files changed

+370
-1
lines changed

src/compiler/transformers/generators.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1478,7 +1478,7 @@ namespace ts {
14781478
}
14791479

14801480
const initializer = node.initializer;
1481-
if (isVariableDeclarationList(initializer)) {
1481+
if (initializer && isVariableDeclarationList(initializer)) {
14821482
for (const variable of initializer.declarations) {
14831483
hoistVariableDeclaration(<Identifier>variable.name);
14841484
}

src/compiler/transformers/module/system.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1287,6 +1287,10 @@ namespace ts {
12871287
* @param node The node to visit.
12881288
*/
12891289
function visitForInitializer(node: ForInitializer): ForInitializer {
1290+
if (!node) {
1291+
return node;
1292+
}
1293+
12901294
if (shouldHoistForInitializer(node)) {
12911295
let expressions: Expression[];
12921296
for (const variable of node.declarations) {
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
//// [SystemModuleForStatementNoInitializer.ts]
2+
3+
export { };
4+
5+
let i = 0;
6+
let limit = 10;
7+
8+
for (; i < limit; ++i) {
9+
break;
10+
}
11+
12+
for (; ; ++i) {
13+
break;
14+
}
15+
16+
for (; ;) {
17+
break;
18+
}
19+
20+
21+
//// [SystemModuleForStatementNoInitializer.js]
22+
System.register([], function (exports_1, context_1) {
23+
"use strict";
24+
var __moduleName = context_1 && context_1.id;
25+
var i, limit;
26+
return {
27+
setters: [],
28+
execute: function () {
29+
i = 0;
30+
limit = 10;
31+
for (; i < limit; ++i) {
32+
break;
33+
}
34+
for (;; ++i) {
35+
break;
36+
}
37+
for (;;) {
38+
break;
39+
}
40+
}
41+
};
42+
});
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
=== tests/cases/compiler/SystemModuleForStatementNoInitializer.ts ===
2+
3+
export { };
4+
5+
let i = 0;
6+
>i : Symbol(i, Decl(SystemModuleForStatementNoInitializer.ts, 3, 3))
7+
8+
let limit = 10;
9+
>limit : Symbol(limit, Decl(SystemModuleForStatementNoInitializer.ts, 4, 3))
10+
11+
for (; i < limit; ++i) {
12+
>i : Symbol(i, Decl(SystemModuleForStatementNoInitializer.ts, 3, 3))
13+
>limit : Symbol(limit, Decl(SystemModuleForStatementNoInitializer.ts, 4, 3))
14+
>i : Symbol(i, Decl(SystemModuleForStatementNoInitializer.ts, 3, 3))
15+
16+
break;
17+
}
18+
19+
for (; ; ++i) {
20+
>i : Symbol(i, Decl(SystemModuleForStatementNoInitializer.ts, 3, 3))
21+
22+
break;
23+
}
24+
25+
for (; ;) {
26+
break;
27+
}
28+
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
=== tests/cases/compiler/SystemModuleForStatementNoInitializer.ts ===
2+
3+
export { };
4+
5+
let i = 0;
6+
>i : number
7+
>0 : 0
8+
9+
let limit = 10;
10+
>limit : number
11+
>10 : 10
12+
13+
for (; i < limit; ++i) {
14+
>i < limit : boolean
15+
>i : number
16+
>limit : number
17+
>++i : number
18+
>i : number
19+
20+
break;
21+
}
22+
23+
for (; ; ++i) {
24+
>++i : number
25+
>i : number
26+
27+
break;
28+
}
29+
30+
for (; ;) {
31+
break;
32+
}
33+
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
//// [asyncFunctionWithForStatementNoInitializer.ts]
2+
async function test1() {
3+
let i = 0
4+
let limit = 10
5+
for (; i < limit; ++i) {
6+
}
7+
}
8+
9+
async function test2() {
10+
let i = 0
11+
let limit = 10
12+
for (i = 1; i < limit; ++i) {
13+
}
14+
}
15+
16+
async function test3() {
17+
let i = 0
18+
for (;; ++i) {
19+
}
20+
}
21+
22+
async function test4() {
23+
for (;;) {
24+
}
25+
}
26+
27+
//// [asyncFunctionWithForStatementNoInitializer.js]
28+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
29+
return new (P || (P = Promise))(function (resolve, reject) {
30+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
31+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
32+
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
33+
step((generator = generator.apply(thisArg, _arguments || [])).next());
34+
});
35+
};
36+
var __generator = (this && this.__generator) || function (thisArg, body) {
37+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
38+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
39+
function verb(n) { return function (v) { return step([n, v]); }; }
40+
function step(op) {
41+
if (f) throw new TypeError("Generator is already executing.");
42+
while (_) try {
43+
if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t;
44+
if (y = 0, t) op = [0, t.value];
45+
switch (op[0]) {
46+
case 0: case 1: t = op; break;
47+
case 4: _.label++; return { value: op[1], done: false };
48+
case 5: _.label++; y = op[1]; op = [0]; continue;
49+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
50+
default:
51+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
52+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
53+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
54+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
55+
if (t[2]) _.ops.pop();
56+
_.trys.pop(); continue;
57+
}
58+
op = body.call(thisArg, _);
59+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
60+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
61+
}
62+
};
63+
function test1() {
64+
return __awaiter(this, void 0, void 0, function () {
65+
var i, limit;
66+
return __generator(this, function (_a) {
67+
i = 0;
68+
limit = 10;
69+
for (; i < limit; ++i) {
70+
}
71+
return [2 /*return*/];
72+
});
73+
});
74+
}
75+
function test2() {
76+
return __awaiter(this, void 0, void 0, function () {
77+
var i, limit;
78+
return __generator(this, function (_a) {
79+
i = 0;
80+
limit = 10;
81+
for (i = 1; i < limit; ++i) {
82+
}
83+
return [2 /*return*/];
84+
});
85+
});
86+
}
87+
function test3() {
88+
return __awaiter(this, void 0, void 0, function () {
89+
var i;
90+
return __generator(this, function (_a) {
91+
i = 0;
92+
for (;; ++i) {
93+
}
94+
return [2 /*return*/];
95+
});
96+
});
97+
}
98+
function test4() {
99+
return __awaiter(this, void 0, void 0, function () {
100+
return __generator(this, function (_a) {
101+
for (;;) {
102+
}
103+
return [2 /*return*/];
104+
});
105+
});
106+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
=== tests/cases/compiler/asyncFunctionWithForStatementNoInitializer.ts ===
2+
async function test1() {
3+
>test1 : Symbol(test1, Decl(asyncFunctionWithForStatementNoInitializer.ts, 0, 0))
4+
5+
let i = 0
6+
>i : Symbol(i, Decl(asyncFunctionWithForStatementNoInitializer.ts, 1, 7))
7+
8+
let limit = 10
9+
>limit : Symbol(limit, Decl(asyncFunctionWithForStatementNoInitializer.ts, 2, 7))
10+
11+
for (; i < limit; ++i) {
12+
>i : Symbol(i, Decl(asyncFunctionWithForStatementNoInitializer.ts, 1, 7))
13+
>limit : Symbol(limit, Decl(asyncFunctionWithForStatementNoInitializer.ts, 2, 7))
14+
>i : Symbol(i, Decl(asyncFunctionWithForStatementNoInitializer.ts, 1, 7))
15+
}
16+
}
17+
18+
async function test2() {
19+
>test2 : Symbol(test2, Decl(asyncFunctionWithForStatementNoInitializer.ts, 5, 1))
20+
21+
let i = 0
22+
>i : Symbol(i, Decl(asyncFunctionWithForStatementNoInitializer.ts, 8, 7))
23+
24+
let limit = 10
25+
>limit : Symbol(limit, Decl(asyncFunctionWithForStatementNoInitializer.ts, 9, 7))
26+
27+
for (i = 1; i < limit; ++i) {
28+
>i : Symbol(i, Decl(asyncFunctionWithForStatementNoInitializer.ts, 8, 7))
29+
>i : Symbol(i, Decl(asyncFunctionWithForStatementNoInitializer.ts, 8, 7))
30+
>limit : Symbol(limit, Decl(asyncFunctionWithForStatementNoInitializer.ts, 9, 7))
31+
>i : Symbol(i, Decl(asyncFunctionWithForStatementNoInitializer.ts, 8, 7))
32+
}
33+
}
34+
35+
async function test3() {
36+
>test3 : Symbol(test3, Decl(asyncFunctionWithForStatementNoInitializer.ts, 12, 1))
37+
38+
let i = 0
39+
>i : Symbol(i, Decl(asyncFunctionWithForStatementNoInitializer.ts, 15, 7))
40+
41+
for (;; ++i) {
42+
>i : Symbol(i, Decl(asyncFunctionWithForStatementNoInitializer.ts, 15, 7))
43+
}
44+
}
45+
46+
async function test4() {
47+
>test4 : Symbol(test4, Decl(asyncFunctionWithForStatementNoInitializer.ts, 18, 1))
48+
49+
for (;;) {
50+
}
51+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
=== tests/cases/compiler/asyncFunctionWithForStatementNoInitializer.ts ===
2+
async function test1() {
3+
>test1 : () => Promise<void>
4+
5+
let i = 0
6+
>i : number
7+
>0 : 0
8+
9+
let limit = 10
10+
>limit : number
11+
>10 : 10
12+
13+
for (; i < limit; ++i) {
14+
>i < limit : boolean
15+
>i : number
16+
>limit : number
17+
>++i : number
18+
>i : number
19+
}
20+
}
21+
22+
async function test2() {
23+
>test2 : () => Promise<void>
24+
25+
let i = 0
26+
>i : number
27+
>0 : 0
28+
29+
let limit = 10
30+
>limit : number
31+
>10 : 10
32+
33+
for (i = 1; i < limit; ++i) {
34+
>i = 1 : 1
35+
>i : number
36+
>1 : 1
37+
>i < limit : boolean
38+
>i : number
39+
>limit : number
40+
>++i : number
41+
>i : number
42+
}
43+
}
44+
45+
async function test3() {
46+
>test3 : () => Promise<void>
47+
48+
let i = 0
49+
>i : number
50+
>0 : 0
51+
52+
for (;; ++i) {
53+
>++i : number
54+
>i : number
55+
}
56+
}
57+
58+
async function test4() {
59+
>test4 : () => Promise<void>
60+
61+
for (;;) {
62+
}
63+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//@module: system
2+
3+
export { };
4+
5+
let i = 0;
6+
let limit = 10;
7+
8+
for (; i < limit; ++i) {
9+
break;
10+
}
11+
12+
for (; ; ++i) {
13+
break;
14+
}
15+
16+
for (; ;) {
17+
break;
18+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
async function test1() {
2+
let i = 0
3+
let limit = 10
4+
for (; i < limit; ++i) {
5+
}
6+
}
7+
8+
async function test2() {
9+
let i = 0
10+
let limit = 10
11+
for (i = 1; i < limit; ++i) {
12+
}
13+
}
14+
15+
async function test3() {
16+
let i = 0
17+
for (;; ++i) {
18+
}
19+
}
20+
21+
async function test4() {
22+
for (;;) {
23+
}
24+
}

0 commit comments

Comments
 (0)