Skip to content

Commit 9584055

Browse files
authored
Prevent valid JSX from being seen as the start of a generic arrow function, fix crashes (#52450)
1 parent 3d07795 commit 9584055

14 files changed

+141
-1
lines changed

src/compiler/parser.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5201,6 +5201,7 @@ namespace Parser {
52015201
switch (fourth) {
52025202
case SyntaxKind.EqualsToken:
52035203
case SyntaxKind.GreaterThanToken:
5204+
case SyntaxKind.SlashToken:
52045205
return false;
52055206
default:
52065207
return true;

src/compiler/utilities.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9079,7 +9079,7 @@ export function rangeOfNode(node: Node): TextRange {
90799079
export function rangeOfTypeParameters(sourceFile: SourceFile, typeParameters: NodeArray<TypeParameterDeclaration>): TextRange {
90809080
// Include the `<>`
90819081
const pos = typeParameters.pos - 1;
9082-
const end = skipTrivia(sourceFile.text, typeParameters.end) + 1;
9082+
const end = Math.min(sourceFile.text.length, skipTrivia(sourceFile.text, typeParameters.end) + 1);
90839083
return { pos, end };
90849084
}
90859085

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//// [index.tsx]
2+
declare const React: any;
3+
4+
export function Foo() {
5+
// No error; "const" is lowercase and therefore intrinsic.
6+
return <const T extends/>
7+
}
8+
9+
10+
//// [index.js]
11+
"use strict";
12+
Object.defineProperty(exports, "__esModule", { value: true });
13+
exports.Foo = void 0;
14+
function Foo() {
15+
// No error; "const" is lowercase and therefore intrinsic.
16+
return React.createElement("const", { T: true, extends: true });
17+
}
18+
exports.Foo = Foo;
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
=== tests/cases/compiler/index.tsx ===
2+
declare const React: any;
3+
>React : Symbol(React, Decl(index.tsx, 0, 13))
4+
5+
export function Foo() {
6+
>Foo : Symbol(Foo, Decl(index.tsx, 0, 25))
7+
8+
// No error; "const" is lowercase and therefore intrinsic.
9+
return <const T extends/>
10+
>T : Symbol(T, Decl(index.tsx, 4, 17))
11+
>extends : Symbol(extends, Decl(index.tsx, 4, 19))
12+
}
13+
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
=== tests/cases/compiler/index.tsx ===
2+
declare const React: any;
3+
>React : any
4+
5+
export function Foo() {
6+
>Foo : () => any
7+
8+
// No error; "const" is lowercase and therefore intrinsic.
9+
return <const T extends/>
10+
><const T extends/> : error
11+
>const : any
12+
>T : true
13+
>extends : true
14+
}
15+
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
tests/cases/compiler/index.tsx(5,13): error TS2304: Cannot find name 'T'.
2+
3+
4+
==== tests/cases/compiler/index.tsx (1 errors) ====
5+
declare const React: any;
6+
7+
export function Foo() {
8+
// Error: T is not declared.
9+
return <T extends/>
10+
~
11+
!!! error TS2304: Cannot find name 'T'.
12+
}
13+
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//// [index.tsx]
2+
declare const React: any;
3+
4+
export function Foo() {
5+
// Error: T is not declared.
6+
return <T extends/>
7+
}
8+
9+
10+
//// [index.js]
11+
"use strict";
12+
Object.defineProperty(exports, "__esModule", { value: true });
13+
exports.Foo = void 0;
14+
function Foo() {
15+
// Error: T is not declared.
16+
return React.createElement(T, { extends: true });
17+
}
18+
exports.Foo = Foo;
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
=== tests/cases/compiler/index.tsx ===
2+
declare const React: any;
3+
>React : Symbol(React, Decl(index.tsx, 0, 13))
4+
5+
export function Foo() {
6+
>Foo : Symbol(Foo, Decl(index.tsx, 0, 25))
7+
8+
// Error: T is not declared.
9+
return <T extends/>
10+
>extends : Symbol(extends, Decl(index.tsx, 4, 13))
11+
}
12+
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
=== tests/cases/compiler/index.tsx ===
2+
declare const React: any;
3+
>React : any
4+
5+
export function Foo() {
6+
>Foo : () => any
7+
8+
// Error: T is not declared.
9+
return <T extends/>
10+
><T extends/> : any
11+
>T : any
12+
>extends : true
13+
}
14+
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// @jsx: react
2+
// @filename: index.tsx
3+
4+
declare const React: any;
5+
6+
export function Foo() {
7+
// No error; "const" is lowercase and therefore intrinsic.
8+
return <const T extends/>
9+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// @jsx: react
2+
// @filename: index.tsx
3+
4+
declare const React: any;
5+
6+
export function Foo() {
7+
// Error: T is not declared.
8+
return <T extends/>
9+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
/// <reference path="fourslash.ts" />
2+
3+
// @filename: index.tsx
4+
//// <const T extends/>
5+
6+
verify.getSuggestionDiagnostics([]);
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
/// <reference path="fourslash.ts" />
2+
3+
// @filename: index.tsx
4+
//// <T extends/>
5+
6+
verify.getSuggestionDiagnostics([]);
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
/// <reference path="fourslash.ts" />
2+
3+
// @filename: index.tsx
4+
//// <T extends /=>
5+
6+
verify.getSuggestionDiagnostics([]);

0 commit comments

Comments
 (0)