mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-04-17 01:49:41 -05:00
Restrict parsing of literals and their expressions a _lot_ more (#17628)
This commit is contained in:
@@ -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>();
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
85
tests/baselines/reference/expressionTypeNodeShouldError.js
Normal file
85
tests/baselines/reference/expressionTypeNodeShouldError.js
Normal 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));
|
||||
45
tests/cases/compiler/expressionTypeNodeShouldError.ts
Normal file
45
tests/cases/compiler/expressionTypeNodeShouldError.ts
Normal 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));
|
||||
|
||||
Reference in New Issue
Block a user