Restrict parsing of literals and their expressions a _lot_ more (#17628)

This commit is contained in:
Wesley Wigham
2017-08-07 09:16:12 -07:00
committed by GitHub
parent 313c93c861
commit a453eff575
4 changed files with 247 additions and 7 deletions

View File

@@ -2061,7 +2061,7 @@ namespace ts {
return <TemplateMiddle | TemplateTail>fragment;
}
function parseLiteralLikeNode(kind: SyntaxKind): LiteralLikeNode {
function parseLiteralLikeNode(kind: SyntaxKind): LiteralExpression | LiteralLikeNode {
const node = <LiteralExpression>createNode(kind);
const text = scanner.getTokenValue();
node.text = text;
@@ -2611,11 +2611,31 @@ namespace ts {
return token() === SyntaxKind.DotToken ? undefined : node;
}
function parseLiteralTypeNode(): LiteralTypeNode {
const node = <LiteralTypeNode>createNode(SyntaxKind.LiteralType);
node.literal = parseSimpleUnaryExpression();
finishNode(node);
return node;
function parseLiteralTypeNode(negative?: boolean): LiteralTypeNode {
const node = createNode(SyntaxKind.LiteralType) as LiteralTypeNode;
let unaryMinusExpression: PrefixUnaryExpression;
if (negative) {
unaryMinusExpression = createNode(SyntaxKind.PrefixUnaryExpression) as PrefixUnaryExpression;
unaryMinusExpression.operator = SyntaxKind.MinusToken;
nextToken();
}
let expression: UnaryExpression;
switch (token()) {
case SyntaxKind.StringLiteral:
case SyntaxKind.NumericLiteral:
expression = parseLiteralLikeNode(token()) as LiteralExpression;
break;
case SyntaxKind.TrueKeyword:
case SyntaxKind.FalseKeyword:
expression = parseTokenNode();
}
if (negative) {
unaryMinusExpression.operand = expression;
finishNode(unaryMinusExpression);
expression = unaryMinusExpression;
}
node.literal = expression;
return finishNode(node);
}
function nextTokenIsNumericLiteral() {
@@ -2650,7 +2670,7 @@ namespace ts {
case SyntaxKind.FalseKeyword:
return parseLiteralTypeNode();
case SyntaxKind.MinusToken:
return lookAhead(nextTokenIsNumericLiteral) ? parseLiteralTypeNode() : parseTypeReference();
return lookAhead(nextTokenIsNumericLiteral) ? parseLiteralTypeNode(/*negative*/ true) : parseTypeReference();
case SyntaxKind.VoidKeyword:
case SyntaxKind.NullKeyword:
return parseTokenNode<TypeNode>();

View File

@@ -0,0 +1,90 @@
tests/cases/compiler/base.d.ts(1,23): error TS1005: ',' expected.
tests/cases/compiler/base.d.ts(1,34): error TS1005: '=' expected.
tests/cases/compiler/boolean.ts(7,23): error TS1005: ',' expected.
tests/cases/compiler/boolean.ts(7,24): error TS1134: Variable declaration expected.
tests/cases/compiler/boolean.ts(11,16): error TS2304: Cannot find name 'document'.
tests/cases/compiler/boolean.ts(12,22): error TS1005: ';' expected.
tests/cases/compiler/number.ts(7,26): error TS1005: ',' expected.
tests/cases/compiler/number.ts(7,27): error TS1134: Variable declaration expected.
tests/cases/compiler/number.ts(11,16): error TS2304: Cannot find name 'document'.
tests/cases/compiler/number.ts(12,20): error TS1005: ';' expected.
tests/cases/compiler/string.ts(7,20): error TS1005: ',' expected.
tests/cases/compiler/string.ts(7,21): error TS1134: Variable declaration expected.
tests/cases/compiler/string.ts(11,15): error TS2304: Cannot find name 'document'.
tests/cases/compiler/string.ts(12,19): error TS1005: ';' expected.
==== tests/cases/compiler/base.d.ts (2 errors) ====
declare const x: "foo".charCodeAt(0);
~
!!! error TS1005: ',' expected.
~
!!! error TS1005: '=' expected.
==== tests/cases/compiler/string.ts (4 errors) ====
interface String {
typeof<T>(x: T): T;
}
class C {
foo() {
const x: "".typeof(this.foo);
~
!!! error TS1005: ',' expected.
~~~~~~
!!! error TS1134: Variable declaration expected.
}
}
const nodes = document.getElementsByTagName("li");
~~~~~~~~
!!! error TS2304: Cannot find name 'document'.
type ItemType = "".typeof(nodes.item(0));
~
!!! error TS1005: ';' expected.
==== tests/cases/compiler/number.ts (4 errors) ====
interface Number {
typeof<T>(x: T): T;
}
class C2 {
foo() {
const x: 3.141592.typeof(this.foo);
~
!!! error TS1005: ',' expected.
~~~~~~
!!! error TS1134: Variable declaration expected.
}
}
const nodes2 = document.getElementsByTagName("li");
~~~~~~~~
!!! error TS2304: Cannot find name 'document'.
type ItemType2 = 4..typeof(nodes.item(0));
~
!!! error TS1005: ';' expected.
==== tests/cases/compiler/boolean.ts (4 errors) ====
interface Boolean {
typeof<T>(x: T): T;
}
class C3 {
foo() {
const x: false.typeof(this.foo);
~
!!! error TS1005: ',' expected.
~~~~~~
!!! error TS1134: Variable declaration expected.
}
}
const nodes3 = document.getElementsByTagName("li");
~~~~~~~~
!!! error TS2304: Cannot find name 'document'.
type ItemType3 = true.typeof(nodes.item(0));
~
!!! error TS1005: ';' expected.

View File

@@ -0,0 +1,85 @@
//// [tests/cases/compiler/expressionTypeNodeShouldError.ts] ////
//// [base.d.ts]
declare const x: "foo".charCodeAt(0);
//// [string.ts]
interface String {
typeof<T>(x: T): T;
}
class C {
foo() {
const x: "".typeof(this.foo);
}
}
const nodes = document.getElementsByTagName("li");
type ItemType = "".typeof(nodes.item(0));
//// [number.ts]
interface Number {
typeof<T>(x: T): T;
}
class C2 {
foo() {
const x: 3.141592.typeof(this.foo);
}
}
const nodes2 = document.getElementsByTagName("li");
type ItemType2 = 4..typeof(nodes.item(0));
//// [boolean.ts]
interface Boolean {
typeof<T>(x: T): T;
}
class C3 {
foo() {
const x: false.typeof(this.foo);
}
}
const nodes3 = document.getElementsByTagName("li");
type ItemType3 = true.typeof(nodes.item(0));
//// [string.js]
var C = (function () {
function C() {
}
C.prototype.foo = function () {
var x;
typeof (this.foo);
};
return C;
}());
var nodes = document.getElementsByTagName("li");
typeof (nodes.item(0));
//// [number.js]
var C2 = (function () {
function C2() {
}
C2.prototype.foo = function () {
var x;
typeof (this.foo);
};
return C2;
}());
var nodes2 = document.getElementsByTagName("li");
typeof (nodes.item(0));
//// [boolean.js]
var C3 = (function () {
function C3() {
}
C3.prototype.foo = function () {
var x;
typeof (this.foo);
};
return C3;
}());
var nodes3 = document.getElementsByTagName("li");
typeof (nodes.item(0));

View File

@@ -0,0 +1,45 @@
// @Filename: base.d.ts
declare const x: "foo".charCodeAt(0);
// @filename: string.ts
interface String {
typeof<T>(x: T): T;
}
class C {
foo() {
const x: "".typeof(this.foo);
}
}
const nodes = document.getElementsByTagName("li");
type ItemType = "".typeof(nodes.item(0));
// @filename: number.ts
interface Number {
typeof<T>(x: T): T;
}
class C2 {
foo() {
const x: 3.141592.typeof(this.foo);
}
}
const nodes2 = document.getElementsByTagName("li");
type ItemType2 = 4..typeof(nodes.item(0));
// @filename: boolean.ts
interface Boolean {
typeof<T>(x: T): T;
}
class C3 {
foo() {
const x: false.typeof(this.foo);
}
}
const nodes3 = document.getElementsByTagName("li");
type ItemType3 = true.typeof(nodes.item(0));