Skip to content

Commit 3a4ac33

Browse files
committed
Merge pull request #5898 from Microsoft/fix3475_let
Disallow let in let/const declaration regardless of target
2 parents 2799d2e + 0784ea1 commit 3a4ac33

File tree

49 files changed

+736
-65
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+736
-65
lines changed

src/compiler/checker.ts

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15965,13 +15965,27 @@ namespace ts {
1596515965
if (forInOrOfStatement.initializer.kind === SyntaxKind.VariableDeclarationList) {
1596615966
const variableList = <VariableDeclarationList>forInOrOfStatement.initializer;
1596715967
if (!checkGrammarVariableDeclarationList(variableList)) {
15968-
if (variableList.declarations.length > 1) {
15968+
const declarations = variableList.declarations;
15969+
15970+
// declarations.length can be zero if there is an error in variable declaration in for-of or for-in
15971+
// See http://www.ecma-international.org/ecma-262/6.0/#sec-for-in-and-for-of-statements for details
15972+
// For example:
15973+
// var let = 10;
15974+
// for (let of [1,2,3]) {} // this is invalid ES6 syntax
15975+
// for (let in [1,2,3]) {} // this is invalid ES6 syntax
15976+
// We will then want to skip on grammar checking on variableList declaration
15977+
if (!declarations.length) {
15978+
return false;
15979+
}
15980+
15981+
if (declarations.length > 1) {
1596915982
const diagnostic = forInOrOfStatement.kind === SyntaxKind.ForInStatement
1597015983
? Diagnostics.Only_a_single_variable_declaration_is_allowed_in_a_for_in_statement
1597115984
: Diagnostics.Only_a_single_variable_declaration_is_allowed_in_a_for_of_statement;
1597215985
return grammarErrorOnFirstToken(variableList.declarations[1], diagnostic);
1597315986
}
15974-
const firstDeclaration = variableList.declarations[0];
15987+
const firstDeclaration = declarations[0];
15988+
1597515989
if (firstDeclaration.initializer) {
1597615990
const diagnostic = forInOrOfStatement.kind === SyntaxKind.ForInStatement
1597715991
? Diagnostics.The_variable_declaration_of_a_for_in_statement_cannot_have_an_initializer
@@ -16170,7 +16184,7 @@ namespace ts {
1617016184
}
1617116185
}
1617216186

16173-
const checkLetConstNames = languageVersion >= ScriptTarget.ES6 && (isLet(node) || isConst(node));
16187+
const checkLetConstNames = (isLet(node) || isConst(node));
1617416188

1617516189
// 1. LexicalDeclaration : LetOrConst BindingList ;
1617616190
// It is a Syntax Error if the BoundNames of BindingList contains "let".
@@ -16184,7 +16198,7 @@ namespace ts {
1618416198

1618516199
function checkGrammarNameInLetOrConstDeclarations(name: Identifier | BindingPattern): boolean {
1618616200
if (name.kind === SyntaxKind.Identifier) {
16187-
if ((<Identifier>name).text === "let") {
16201+
if ((<Identifier>name).originalKeywordKind === SyntaxKind.LetKeyword) {
1618816202
return grammarErrorOnNode(name, Diagnostics.let_is_not_allowed_to_be_used_as_a_name_in_let_or_const_declarations);
1618916203
}
1619016204
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
tests/cases/compiler/invalidLetInForOfAndForIn_ES5.ts(5,13): error TS1005: '=' expected.
2+
tests/cases/compiler/invalidLetInForOfAndForIn_ES5.ts(5,20): error TS1005: ',' expected.
3+
tests/cases/compiler/invalidLetInForOfAndForIn_ES5.ts(7,1): error TS1005: ';' expected.
4+
5+
6+
==== tests/cases/compiler/invalidLetInForOfAndForIn_ES5.ts (3 errors) ====
7+
// This should be an error
8+
// More details: http://www.ecma-international.org/ecma-262/6.0/#sec-iteration-statements
9+
10+
var let = 10;
11+
for (let of [1,2,3]) {}
12+
~
13+
!!! error TS1005: '=' expected.
14+
~
15+
!!! error TS1005: ',' expected.
16+
17+
for (let in [1,2,3]) {}
18+
~~~
19+
!!! error TS1005: ';' expected.
20+
21+
22+
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//// [invalidLetInForOfAndForIn_ES5.ts]
2+
// This should be an error
3+
// More details: http://www.ecma-international.org/ecma-262/6.0/#sec-iteration-statements
4+
5+
var let = 10;
6+
for (let of [1,2,3]) {}
7+
8+
for (let in [1,2,3]) {}
9+
10+
11+
12+
13+
//// [invalidLetInForOfAndForIn_ES5.js]
14+
// This should be an error
15+
// More details: http://www.ecma-international.org/ecma-262/6.0/#sec-iteration-statements
16+
var let = 10;
17+
for (let of = [1, 2, 3], { }; ; )
18+
for ( in [1, 2, 3]) { }
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
tests/cases/compiler/invalidLetInForOfAndForIn_ES6.ts(5,13): error TS1005: '=' expected.
2+
tests/cases/compiler/invalidLetInForOfAndForIn_ES6.ts(5,20): error TS1005: ',' expected.
3+
tests/cases/compiler/invalidLetInForOfAndForIn_ES6.ts(7,1): error TS1005: ';' expected.
4+
5+
6+
==== tests/cases/compiler/invalidLetInForOfAndForIn_ES6.ts (3 errors) ====
7+
// This should be an error
8+
// More details: http://www.ecma-international.org/ecma-262/6.0/#sec-iteration-statements
9+
10+
var let = 10;
11+
for (let of [1,2,3]) {}
12+
~
13+
!!! error TS1005: '=' expected.
14+
~
15+
!!! error TS1005: ',' expected.
16+
17+
for (let in [1,2,3]) {}
18+
~~~
19+
!!! error TS1005: ';' expected.
20+
21+
22+
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//// [invalidLetInForOfAndForIn_ES6.ts]
2+
// This should be an error
3+
// More details: http://www.ecma-international.org/ecma-262/6.0/#sec-iteration-statements
4+
5+
var let = 10;
6+
for (let of [1,2,3]) {}
7+
8+
for (let in [1,2,3]) {}
9+
10+
11+
12+
13+
//// [invalidLetInForOfAndForIn_ES6.js]
14+
// This should be an error
15+
// More details: http://www.ecma-international.org/ecma-262/6.0/#sec-iteration-statements
16+
var let = 10;
17+
for (let of = [1, 2, 3], { }; ; )
18+
for ( in [1, 2, 3]) { }
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
//// [letAsIdentifier2.ts]
2+
3+
function let() {}
4+
5+
//// [letAsIdentifier2.js]
6+
function let() { }
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
=== tests/cases/compiler/letAsIdentifier2.ts ===
2+
3+
function let() {}
4+
>let : Symbol(let, Decl(letAsIdentifier2.ts, 0, 0))
5+
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
=== tests/cases/compiler/letAsIdentifier2.ts ===
2+
3+
function let() {}
4+
>let : () => void
5+
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
tests/cases/compiler/letInConstDeclarations_ES5.ts(3,15): error TS2480: 'let' is not allowed to be used as a name in 'let' or 'const' declarations.
2+
tests/cases/compiler/letInConstDeclarations_ES5.ts(6,19): error TS2480: 'let' is not allowed to be used as a name in 'let' or 'const' declarations.
3+
4+
5+
==== tests/cases/compiler/letInConstDeclarations_ES5.ts (2 errors) ====
6+
7+
// All use of let in const declaration should be an error
8+
const x = 50, let = 5;
9+
~~~
10+
!!! error TS2480: 'let' is not allowed to be used as a name in 'let' or 'const' declarations.
11+
12+
{
13+
const x = 10, let = 20;
14+
~~~
15+
!!! error TS2480: 'let' is not allowed to be used as a name in 'let' or 'const' declarations.
16+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//// [letInConstDeclarations_ES5.ts]
2+
3+
// All use of let in const declaration should be an error
4+
const x = 50, let = 5;
5+
6+
{
7+
const x = 10, let = 20;
8+
}
9+
10+
//// [letInConstDeclarations_ES5.js]
11+
// All use of let in const declaration should be an error
12+
var x = 50, let = 5;
13+
{
14+
var x_1 = 10, let_1 = 20;
15+
}

0 commit comments

Comments
 (0)