Skip to content

Commit 0da9b7a

Browse files
committed
Merge pull request #3942 from RyanCavanaugh/fix3903
Fix crash when the element instance type was undefined
2 parents 4f507a6 + 4e3751c commit 0da9b7a

File tree

8 files changed

+237
-57
lines changed

8 files changed

+237
-57
lines changed

src/compiler/checker.ts

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7324,10 +7324,9 @@ namespace ts {
73247324
* For example, in the element <MyClass>, the element instance type is `MyClass` (not `typeof MyClass`).
73257325
*/
73267326
function getJsxElementInstanceType(node: JsxOpeningLikeElement) {
7327-
if (!(getNodeLinks(node).jsxFlags & JsxFlags.ClassElement)) {
7328-
// There is no such thing as an instance type for a non-class element
7329-
return undefined;
7330-
}
7327+
// There is no such thing as an instance type for a non-class element. This
7328+
// line shouldn't be hit.
7329+
Debug.assert(!!(getNodeLinks(node).jsxFlags & JsxFlags.ClassElement), 'Should not call getJsxElementInstanceType on non-class Element');
73317330

73327331
let classSymbol = getJsxElementTagSymbol(node);
73337332
if (classSymbol === unknownSymbol) {
@@ -7350,16 +7349,11 @@ namespace ts {
73507349
if (signatures.length === 0) {
73517350
// We found no signatures at all, which is an error
73527351
error(node.tagName, Diagnostics.JSX_element_type_0_does_not_have_any_construct_or_call_signatures, getTextOfNode(node.tagName));
7353-
return undefined;
7352+
return unknownType;
73547353
}
73557354
}
73567355

7357-
// Check that the constructor/factory returns an object type
7358-
let returnType = getUnionType(signatures.map(s => getReturnTypeOfSignature(s)));
7359-
if (!isTypeAny(returnType) && !(returnType.flags & TypeFlags.ObjectType)) {
7360-
error(node.tagName, Diagnostics.The_return_type_of_a_JSX_element_constructor_must_return_an_object_type);
7361-
return undefined;
7362-
}
7356+
let returnType = getUnionType(signatures.map(getReturnTypeOfSignature));
73637357

73647358
// Issue an error if this return type isn't assignable to JSX.ElementClass
73657359
let elemClassType = getJsxGlobalElementClassType();
@@ -7420,7 +7414,7 @@ namespace ts {
74207414
let elemInstanceType = getJsxElementInstanceType(node);
74217415

74227416
if (isTypeAny(elemInstanceType)) {
7423-
return links.resolvedJsxType = anyType;
7417+
return links.resolvedJsxType = elemInstanceType;
74247418
}
74257419

74267420
let propsName = getJsxElementPropertiesName();
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
tests/cases/compiler/consumer.tsx(5,17): error TS2604: JSX element type 'BaseComponent' does not have any construct or call signatures.
2+
3+
4+
==== tests/cases/compiler/consumer.tsx (1 errors) ====
5+
/// <reference path="component.d.ts" />
6+
import BaseComponent = require('BaseComponent');
7+
class TestComponent extends React.Component<any, {}> {
8+
render() {
9+
return <BaseComponent />;
10+
~~~~~~~~~~~~~
11+
!!! error TS2604: JSX element type 'BaseComponent' does not have any construct or call signatures.
12+
}
13+
}
14+
15+
==== tests/cases/compiler/component.d.ts (0 errors) ====
16+
17+
declare module JSX {
18+
interface ElementAttributesProperty { props; }
19+
}
20+
declare module React {
21+
class Component<T, U> { }
22+
}
23+
declare module "BaseComponent" {
24+
var base: React.Component<any, {}>;
25+
export = base;
26+
}
27+
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
//// [tests/cases/compiler/jsxViaImport.tsx] ////
2+
3+
//// [component.d.ts]
4+
5+
declare module JSX {
6+
interface ElementAttributesProperty { props; }
7+
}
8+
declare module React {
9+
class Component<T, U> { }
10+
}
11+
declare module "BaseComponent" {
12+
var base: React.Component<any, {}>;
13+
export = base;
14+
}
15+
16+
//// [consumer.tsx]
17+
/// <reference path="component.d.ts" />
18+
import BaseComponent = require('BaseComponent');
19+
class TestComponent extends React.Component<any, {}> {
20+
render() {
21+
return <BaseComponent />;
22+
}
23+
}
24+
25+
26+
//// [consumer.jsx]
27+
var __extends = (this && this.__extends) || function (d, b) {
28+
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
29+
function __() { this.constructor = d; }
30+
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
31+
};
32+
/// <reference path="component.d.ts" />
33+
var BaseComponent = require('BaseComponent');
34+
var TestComponent = (function (_super) {
35+
__extends(TestComponent, _super);
36+
function TestComponent() {
37+
_super.apply(this, arguments);
38+
}
39+
TestComponent.prototype.render = function () {
40+
return <BaseComponent />;
41+
};
42+
return TestComponent;
43+
})(React.Component);

tests/baselines/reference/tsxElementResolution8.errors.txt

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
tests/cases/conformance/jsx/tsxElementResolution8.tsx(8,2): error TS2604: JSX element type 'Div' does not have any construct or call signatures.
2-
tests/cases/conformance/jsx/tsxElementResolution8.tsx(16,2): error TS2601: The return type of a JSX element constructor must return an object type.
3-
tests/cases/conformance/jsx/tsxElementResolution8.tsx(29,2): error TS2601: The return type of a JSX element constructor must return an object type.
42
tests/cases/conformance/jsx/tsxElementResolution8.tsx(34,2): error TS2604: JSX element type 'Obj3' does not have any construct or call signatures.
53

64

7-
==== tests/cases/conformance/jsx/tsxElementResolution8.tsx (4 errors) ====
5+
==== tests/cases/conformance/jsx/tsxElementResolution8.tsx (2 errors) ====
86
declare module JSX {
97
interface Element { }
108
interface IntrinsicElements { }
@@ -23,8 +21,6 @@ tests/cases/conformance/jsx/tsxElementResolution8.tsx(34,2): error TS2604: JSX e
2321
// Error
2422
function Fnum(): number{ return 42; }
2523
<Fnum />
26-
~~~~
27-
!!! error TS2601: The return type of a JSX element constructor must return an object type.
2824

2925
interface Obj1 {
3026
new(): {};
@@ -38,8 +34,6 @@ tests/cases/conformance/jsx/tsxElementResolution8.tsx(34,2): error TS2604: JSX e
3834
}
3935
var Obj2: Obj2;
4036
<Obj2 />; // Error
41-
~~~~
42-
!!! error TS2601: The return type of a JSX element constructor must return an object type.
4337

4438
interface Obj3 {
4539
}

tests/baselines/reference/tsxElementResolution9.errors.txt

Lines changed: 0 additions & 38 deletions
This file was deleted.
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
=== tests/cases/conformance/jsx/tsxElementResolution9.tsx ===
2+
declare module JSX {
3+
>JSX : Symbol(JSX, Decl(tsxElementResolution9.tsx, 0, 0))
4+
5+
interface Element { }
6+
>Element : Symbol(Element, Decl(tsxElementResolution9.tsx, 0, 20))
7+
8+
interface IntrinsicElements { }
9+
>IntrinsicElements : Symbol(IntrinsicElements, Decl(tsxElementResolution9.tsx, 1, 22))
10+
}
11+
12+
interface Obj1 {
13+
>Obj1 : Symbol(Obj1, Decl(tsxElementResolution9.tsx, 3, 1), Decl(tsxElementResolution9.tsx, 9, 3))
14+
15+
new(n: string): { x: number };
16+
>n : Symbol(n, Decl(tsxElementResolution9.tsx, 6, 5))
17+
>x : Symbol(x, Decl(tsxElementResolution9.tsx, 6, 18))
18+
19+
new(n: number): { y: string };
20+
>n : Symbol(n, Decl(tsxElementResolution9.tsx, 7, 5))
21+
>y : Symbol(y, Decl(tsxElementResolution9.tsx, 7, 18))
22+
}
23+
var Obj1: Obj1;
24+
>Obj1 : Symbol(Obj1, Decl(tsxElementResolution9.tsx, 3, 1), Decl(tsxElementResolution9.tsx, 9, 3))
25+
>Obj1 : Symbol(Obj1, Decl(tsxElementResolution9.tsx, 3, 1), Decl(tsxElementResolution9.tsx, 9, 3))
26+
27+
<Obj1 />; // Error, return type is not an object type
28+
>Obj1 : Symbol(Obj1, Decl(tsxElementResolution9.tsx, 3, 1), Decl(tsxElementResolution9.tsx, 9, 3))
29+
30+
interface Obj2 {
31+
>Obj2 : Symbol(Obj2, Decl(tsxElementResolution9.tsx, 10, 9), Decl(tsxElementResolution9.tsx, 16, 3))
32+
33+
(n: string): { x: number };
34+
>n : Symbol(n, Decl(tsxElementResolution9.tsx, 13, 2))
35+
>x : Symbol(x, Decl(tsxElementResolution9.tsx, 13, 15))
36+
37+
(n: number): { y: string };
38+
>n : Symbol(n, Decl(tsxElementResolution9.tsx, 14, 2))
39+
>y : Symbol(y, Decl(tsxElementResolution9.tsx, 14, 15))
40+
}
41+
var Obj2: Obj2;
42+
>Obj2 : Symbol(Obj2, Decl(tsxElementResolution9.tsx, 10, 9), Decl(tsxElementResolution9.tsx, 16, 3))
43+
>Obj2 : Symbol(Obj2, Decl(tsxElementResolution9.tsx, 10, 9), Decl(tsxElementResolution9.tsx, 16, 3))
44+
45+
<Obj2 />; // Error, return type is not an object type
46+
>Obj2 : Symbol(Obj2, Decl(tsxElementResolution9.tsx, 10, 9), Decl(tsxElementResolution9.tsx, 16, 3))
47+
48+
interface Obj3 {
49+
>Obj3 : Symbol(Obj3, Decl(tsxElementResolution9.tsx, 17, 9), Decl(tsxElementResolution9.tsx, 23, 3))
50+
51+
(n: string): { x: number };
52+
>n : Symbol(n, Decl(tsxElementResolution9.tsx, 20, 2))
53+
>x : Symbol(x, Decl(tsxElementResolution9.tsx, 20, 15))
54+
55+
(n: number): { x: number; y: string };
56+
>n : Symbol(n, Decl(tsxElementResolution9.tsx, 21, 2))
57+
>x : Symbol(x, Decl(tsxElementResolution9.tsx, 21, 15))
58+
>y : Symbol(y, Decl(tsxElementResolution9.tsx, 21, 26))
59+
}
60+
var Obj3: Obj3;
61+
>Obj3 : Symbol(Obj3, Decl(tsxElementResolution9.tsx, 17, 9), Decl(tsxElementResolution9.tsx, 23, 3))
62+
>Obj3 : Symbol(Obj3, Decl(tsxElementResolution9.tsx, 17, 9), Decl(tsxElementResolution9.tsx, 23, 3))
63+
64+
<Obj3 x={42} />; // OK
65+
>Obj3 : Symbol(Obj3, Decl(tsxElementResolution9.tsx, 17, 9), Decl(tsxElementResolution9.tsx, 23, 3))
66+
>x : Symbol(unknown)
67+
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
=== tests/cases/conformance/jsx/tsxElementResolution9.tsx ===
2+
declare module JSX {
3+
>JSX : any
4+
5+
interface Element { }
6+
>Element : Element
7+
8+
interface IntrinsicElements { }
9+
>IntrinsicElements : IntrinsicElements
10+
}
11+
12+
interface Obj1 {
13+
>Obj1 : Obj1
14+
15+
new(n: string): { x: number };
16+
>n : string
17+
>x : number
18+
19+
new(n: number): { y: string };
20+
>n : number
21+
>y : string
22+
}
23+
var Obj1: Obj1;
24+
>Obj1 : Obj1
25+
>Obj1 : Obj1
26+
27+
<Obj1 />; // Error, return type is not an object type
28+
><Obj1 /> : JSX.Element
29+
>Obj1 : Obj1
30+
31+
interface Obj2 {
32+
>Obj2 : Obj2
33+
34+
(n: string): { x: number };
35+
>n : string
36+
>x : number
37+
38+
(n: number): { y: string };
39+
>n : number
40+
>y : string
41+
}
42+
var Obj2: Obj2;
43+
>Obj2 : Obj2
44+
>Obj2 : Obj2
45+
46+
<Obj2 />; // Error, return type is not an object type
47+
><Obj2 /> : JSX.Element
48+
>Obj2 : Obj2
49+
50+
interface Obj3 {
51+
>Obj3 : Obj3
52+
53+
(n: string): { x: number };
54+
>n : string
55+
>x : number
56+
57+
(n: number): { x: number; y: string };
58+
>n : number
59+
>x : number
60+
>y : string
61+
}
62+
var Obj3: Obj3;
63+
>Obj3 : Obj3
64+
>Obj3 : Obj3
65+
66+
<Obj3 x={42} />; // OK
67+
><Obj3 x={42} /> : JSX.Element
68+
>Obj3 : Obj3
69+
>x : any
70+

tests/cases/compiler/jsxViaImport.tsx

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//@jsx: preserve
2+
//@module: commonjs
3+
4+
//@filename: component.d.ts
5+
declare module JSX {
6+
interface ElementAttributesProperty { props; }
7+
}
8+
declare module React {
9+
class Component<T, U> { }
10+
}
11+
declare module "BaseComponent" {
12+
var base: React.Component<any, {}>;
13+
export = base;
14+
}
15+
16+
//@filename: consumer.tsx
17+
/// <reference path="component.d.ts" />
18+
import BaseComponent = require('BaseComponent');
19+
class TestComponent extends React.Component<any, {}> {
20+
render() {
21+
return <BaseComponent />;
22+
}
23+
}

0 commit comments

Comments
 (0)