Skip to content

Commit 6203675

Browse files
Merge pull request #2809 from Microsoft/noReservedWordsInBindingPatterns
Disallow reserved words for object binding pattern names
2 parents bf51a34 + 4134d79 commit 6203675

25 files changed

+157
-19
lines changed

src/compiler/checker.ts

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6161,9 +6161,7 @@ module ts {
61616161
}
61626162
else {
61636163
Debug.assert(memberDecl.kind === SyntaxKind.ShorthandPropertyAssignment);
6164-
type = memberDecl.name.kind === SyntaxKind.ComputedPropertyName
6165-
? unknownType
6166-
: checkExpression(<Identifier>memberDecl.name, contextualMapper);
6164+
type = checkExpression((<ShorthandPropertyAssignment>memberDecl).name, contextualMapper);
61676165
}
61686166
typeFlags |= type.flags;
61696167
let prop = <TransientSymbol>createSymbol(SymbolFlags.Property | SymbolFlags.Transient | member.flags, member.name);
@@ -8053,7 +8051,7 @@ module ts {
80538051

80548052
function checkNumericLiteral(node: LiteralExpression): Type {
80558053
// Grammar checking
8056-
checkGrammarNumbericLiteral(node);
8054+
checkGrammarNumericLiteral(node);
80578055
return numberType;
80588056
}
80598057

@@ -12017,8 +12015,8 @@ module ts {
1201712015
}
1201812016

1201912017
// GRAMMAR CHECKING
12020-
function isReservedwordInStrictMode(node: Identifier): boolean {
12021-
// Check that originalKeywordKind is less than LastFurtureReservedWord to see if an Identifier is a strict-mode reserved word
12018+
function isReservedWordInStrictMode(node: Identifier): boolean {
12019+
// Check that originalKeywordKind is less than LastFutureReservedWord to see if an Identifier is a strict-mode reserved word
1202212020
return (node.parserContextFlags & ParserContextFlags.StrictMode) &&
1202312021
(node.originalKeywordKind >= SyntaxKind.FirstFutureReservedWord && node.originalKeywordKind <= SyntaxKind.LastFutureReservedWord);
1202412022
}
@@ -12063,7 +12061,7 @@ module ts {
1206312061

1206412062
function checkGrammarDeclarationNameInStrictMode(node: Declaration): boolean {
1206512063
let name = node.name;
12066-
if (name && name.kind === SyntaxKind.Identifier && isReservedwordInStrictMode(<Identifier>name)) {
12064+
if (name && name.kind === SyntaxKind.Identifier && isReservedWordInStrictMode(<Identifier>name)) {
1206712065
let nameText = declarationNameToString(name);
1206812066
switch (node.kind) {
1206912067
case SyntaxKind.Parameter:
@@ -12139,7 +12137,7 @@ module ts {
1213912137

1214012138
// The function takes an identifier itself or an expression which has SyntaxKind.Identifier.
1214112139
function checkGrammarIdentifierInStrictMode(node: Expression | Identifier, nameText?: string): boolean {
12142-
if (node && node.kind === SyntaxKind.Identifier && isReservedwordInStrictMode(<Identifier>node)) {
12140+
if (node && node.kind === SyntaxKind.Identifier && isReservedWordInStrictMode(<Identifier>node)) {
1214312141
if (!nameText) {
1214412142
nameText = declarationNameToString(<Identifier>node);
1214512143
}
@@ -12154,7 +12152,7 @@ module ts {
1215412152

1215512153
// The function takes an identifier when uses as a typeName in TypeReferenceNode
1215612154
function checkGrammarTypeNameInStrictMode(node: Identifier): boolean {
12157-
if (node && node.kind === SyntaxKind.Identifier && isReservedwordInStrictMode(<Identifier>node)) {
12155+
if (node && node.kind === SyntaxKind.Identifier && isReservedWordInStrictMode(<Identifier>node)) {
1215812156
let nameText = declarationNameToString(<Identifier>node);
1215912157

1216012158
// TODO (yuisu): Fix when module is a strict mode
@@ -12606,7 +12604,7 @@ module ts {
1260612604
// Grammar checking for computedPropertName and shorthandPropertyAssignment
1260712605
checkGrammarForInvalidQuestionMark(prop,(<PropertyAssignment>prop).questionToken, Diagnostics.An_object_member_cannot_be_declared_optional);
1260812606
if (name.kind === SyntaxKind.NumericLiteral) {
12609-
checkGrammarNumbericLiteral(<Identifier>name);
12607+
checkGrammarNumericLiteral(<Identifier>name);
1261012608
}
1261112609
currentKind = Property;
1261212610
}
@@ -13158,7 +13156,7 @@ module ts {
1315813156
}
1315913157
}
1316013158

13161-
function checkGrammarNumbericLiteral(node: Identifier): boolean {
13159+
function checkGrammarNumericLiteral(node: Identifier): boolean {
1316213160
// Grammar checking
1316313161
if (node.flags & NodeFlags.OctalLiteral) {
1316413162
if (node.parserContextFlags & ParserContextFlags.StrictMode) {

src/compiler/parser.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3859,13 +3859,14 @@ module ts {
38593859
function parseObjectBindingElement(): BindingElement {
38603860
let node = <BindingElement>createNode(SyntaxKind.BindingElement);
38613861
// TODO(andersh): Handle computed properties
3862-
let id = parsePropertyName();
3863-
if (id.kind === SyntaxKind.Identifier && token !== SyntaxKind.ColonToken) {
3864-
node.name = <Identifier>id;
3862+
let tokenIsIdentifier = isIdentifier();
3863+
let propertyName = parsePropertyName();
3864+
if (tokenIsIdentifier && token !== SyntaxKind.ColonToken) {
3865+
node.name = <Identifier>propertyName;
38653866
}
38663867
else {
38673868
parseExpected(SyntaxKind.ColonToken);
3868-
node.propertyName = <Identifier>id;
3869+
node.propertyName = <Identifier>propertyName;
38693870
node.name = parseIdentifierOrPattern();
38703871
}
38713872
node.initializer = parseInitializer(/*inParameter*/ false);

src/compiler/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -389,7 +389,7 @@ module ts {
389389

390390
export interface Identifier extends PrimaryExpression {
391391
text: string; // Text of identifier (with escapes converted to characters)
392-
originalKeywordKind?: SyntaxKind; // Original syntaxKind which get set so that we can report an error later
392+
originalKeywordKind?: SyntaxKind; // Original syntaxKind which get set so that we can report an error later
393393
}
394394

395395
export interface QualifiedName extends Node {
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
tests/cases/conformance/es6/destructuring/objectBindingPatternKeywordIdentifiers01.ts(2,13): error TS1005: ':' expected.
2+
3+
4+
==== tests/cases/conformance/es6/destructuring/objectBindingPatternKeywordIdentifiers01.ts (1 errors) ====
5+
6+
var { while } = { while: 1 }
7+
~
8+
!!! error TS1005: ':' expected.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
//// [objectBindingPatternKeywordIdentifiers01.ts]
2+
3+
var { while } = { while: 1 }
4+
5+
//// [objectBindingPatternKeywordIdentifiers01.js]
6+
var = { while: 1 }.while;
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
tests/cases/conformance/es6/destructuring/objectBindingPatternKeywordIdentifiers02.ts(2,14): error TS1003: Identifier expected.
2+
tests/cases/conformance/es6/destructuring/objectBindingPatternKeywordIdentifiers02.ts(2,20): error TS1005: ':' expected.
3+
4+
5+
==== tests/cases/conformance/es6/destructuring/objectBindingPatternKeywordIdentifiers02.ts (2 errors) ====
6+
7+
var { while: while } = { while: 1 }
8+
~~~~~
9+
!!! error TS1003: Identifier expected.
10+
~
11+
!!! error TS1005: ':' expected.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
//// [objectBindingPatternKeywordIdentifiers02.ts]
2+
3+
var { while: while } = { while: 1 }
4+
5+
//// [objectBindingPatternKeywordIdentifiers02.js]
6+
var _a = { while: 1 }, = _a.while, = _a.while;
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
tests/cases/conformance/es6/destructuring/objectBindingPatternKeywordIdentifiers03.ts(2,15): error TS1005: ':' expected.
2+
3+
4+
==== tests/cases/conformance/es6/destructuring/objectBindingPatternKeywordIdentifiers03.ts (1 errors) ====
5+
6+
var { "while" } = { while: 1 }
7+
~
8+
!!! error TS1005: ':' expected.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
//// [objectBindingPatternKeywordIdentifiers03.ts]
2+
3+
var { "while" } = { while: 1 }
4+
5+
//// [objectBindingPatternKeywordIdentifiers03.js]
6+
var = { while: 1 }["while"];
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
tests/cases/conformance/es6/destructuring/objectBindingPatternKeywordIdentifiers04.ts(2,16): error TS1003: Identifier expected.
2+
tests/cases/conformance/es6/destructuring/objectBindingPatternKeywordIdentifiers04.ts(2,22): error TS1005: ':' expected.
3+
4+
5+
==== tests/cases/conformance/es6/destructuring/objectBindingPatternKeywordIdentifiers04.ts (2 errors) ====
6+
7+
var { "while": while } = { while: 1 }
8+
~~~~~
9+
!!! error TS1003: Identifier expected.
10+
~
11+
!!! error TS1005: ':' expected.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
//// [objectBindingPatternKeywordIdentifiers04.ts]
2+
3+
var { "while": while } = { while: 1 }
4+
5+
//// [objectBindingPatternKeywordIdentifiers04.js]
6+
var _a = { while: 1 }, = _a["while"], = _a.while;
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
//// [objectBindingPatternKeywordIdentifiers05.ts]
2+
3+
var { as } = { as: 1 }
4+
5+
//// [objectBindingPatternKeywordIdentifiers05.js]
6+
var as = { as: 1 }.as;
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
=== tests/cases/conformance/es6/destructuring/objectBindingPatternKeywordIdentifiers05.ts ===
2+
3+
var { as } = { as: 1 }
4+
>as : Symbol(as, Decl(objectBindingPatternKeywordIdentifiers05.ts, 1, 5))
5+
>as : Symbol(as, Decl(objectBindingPatternKeywordIdentifiers05.ts, 1, 14))
6+
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
=== tests/cases/conformance/es6/destructuring/objectBindingPatternKeywordIdentifiers05.ts ===
2+
3+
var { as } = { as: 1 }
4+
>as : number
5+
>{ as: 1 } : { as: number; }
6+
>as : number
7+
>1 : number
8+
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
//// [objectBindingPatternKeywordIdentifiers06.ts]
2+
3+
var { as: as } = { as: 1 }
4+
5+
//// [objectBindingPatternKeywordIdentifiers06.js]
6+
var as = { as: 1 }.as;
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
=== tests/cases/conformance/es6/destructuring/objectBindingPatternKeywordIdentifiers06.ts ===
2+
3+
var { as: as } = { as: 1 }
4+
>as : Symbol(as, Decl(objectBindingPatternKeywordIdentifiers06.ts, 1, 5))
5+
>as : Symbol(as, Decl(objectBindingPatternKeywordIdentifiers06.ts, 1, 18))
6+
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
=== tests/cases/conformance/es6/destructuring/objectBindingPatternKeywordIdentifiers06.ts ===
2+
3+
var { as: as } = { as: 1 }
4+
>as : any
5+
>as : number
6+
>{ as: 1 } : { as: number; }
7+
>as : number
8+
>1 : number
9+

tests/baselines/reference/reservedWords2.errors.txt

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,14 @@ tests/cases/compiler/reservedWords2.ts(5,10): error TS1003: Identifier expected.
1515
tests/cases/compiler/reservedWords2.ts(5,18): error TS1005: '=>' expected.
1616
tests/cases/compiler/reservedWords2.ts(6,7): error TS2300: Duplicate identifier '(Missing)'.
1717
tests/cases/compiler/reservedWords2.ts(6,8): error TS1003: Identifier expected.
18+
tests/cases/compiler/reservedWords2.ts(7,11): error TS2300: Duplicate identifier '(Missing)'.
19+
tests/cases/compiler/reservedWords2.ts(7,11): error TS1005: ':' expected.
20+
tests/cases/compiler/reservedWords2.ts(7,19): error TS2300: Duplicate identifier '(Missing)'.
21+
tests/cases/compiler/reservedWords2.ts(7,19): error TS1005: ':' expected.
22+
tests/cases/compiler/reservedWords2.ts(8,10): error TS2300: Duplicate identifier '(Missing)'.
23+
tests/cases/compiler/reservedWords2.ts(8,10): error TS1005: ':' expected.
24+
tests/cases/compiler/reservedWords2.ts(8,30): error TS2300: Duplicate identifier '(Missing)'.
25+
tests/cases/compiler/reservedWords2.ts(8,30): error TS1005: ':' expected.
1826
tests/cases/compiler/reservedWords2.ts(9,6): error TS1181: Array element destructuring pattern expected.
1927
tests/cases/compiler/reservedWords2.ts(9,14): error TS1005: ';' expected.
2028
tests/cases/compiler/reservedWords2.ts(9,18): error TS1005: '(' expected.
@@ -23,7 +31,7 @@ tests/cases/compiler/reservedWords2.ts(10,5): error TS2300: Duplicate identifier
2331
tests/cases/compiler/reservedWords2.ts(10,6): error TS1003: Identifier expected.
2432

2533

26-
==== tests/cases/compiler/reservedWords2.ts (23 errors) ====
34+
==== tests/cases/compiler/reservedWords2.ts (31 errors) ====
2735
import while = require("dfdf");
2836
~~~~~~
2937
!!! error TS1148: Cannot compile external modules unless the '--module' flag is provided.
@@ -65,7 +73,23 @@ tests/cases/compiler/reservedWords2.ts(10,6): error TS1003: Identifier expected.
6573
~~~~
6674
!!! error TS1003: Identifier expected.
6775
var {while, return} = { while: 1, return: 2 };
76+
77+
!!! error TS2300: Duplicate identifier '(Missing)'.
78+
~
79+
!!! error TS1005: ':' expected.
80+
81+
!!! error TS2300: Duplicate identifier '(Missing)'.
82+
~
83+
!!! error TS1005: ':' expected.
6884
var {this, switch: { continue} } = { this: 1, switch: { continue: 2 }};
85+
86+
!!! error TS2300: Duplicate identifier '(Missing)'.
87+
~
88+
!!! error TS1005: ':' expected.
89+
90+
!!! error TS2300: Duplicate identifier '(Missing)'.
91+
~
92+
!!! error TS1005: ':' expected.
6993
var [debugger, if] = [1, 2];
7094
~~~~~~~~
7195
!!! error TS1181: Array element destructuring pattern expected.

tests/baselines/reference/reservedWords2.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ typeof ;
2424
10;
2525
throw function () { };
2626
void {};
27-
var _a = { while: 1, return: 2 }, while = _a.while, return = _a.return;
28-
var _b = { this: 1, switch: { continue: 2 } }, this = _b.this, continue = _b.switch.continue;
27+
var _a = { while: 1, return: 2 }, = _a.while, = _a.return;
28+
var _b = { this: 1, switch: { continue: 2 } }, = _b.this, = _b.switch.continue;
2929
var _c = void 0;
3030
debugger;
3131
if ()
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+

2+
var { while } = { while: 1 }
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+

2+
var { while: while } = { while: 1 }
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+

2+
var { "while" } = { while: 1 }
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+

2+
var { "while": while } = { while: 1 }
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+

2+
var { as } = { as: 1 }
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+

2+
var { as: as } = { as: 1 }

0 commit comments

Comments
 (0)