Skip to content

Commit 76b1e95

Browse files
committed
Always call checkExpression on JSX attribute values
Fixes microsoft#13676
1 parent abc30b2 commit 76b1e95

File tree

5 files changed

+239
-9
lines changed

5 files changed

+239
-9
lines changed

src/compiler/checker.ts

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11879,6 +11879,16 @@ namespace ts {
1187911879
function checkJsxAttribute(node: JsxAttribute, elementAttributesType: Type, nameTable: Map<boolean>) {
1188011880
let correspondingPropType: Type = undefined;
1188111881

11882+
// We need to unconditionally get the expression type
11883+
let exprType: Type;
11884+
if (node.initializer) {
11885+
exprType = checkExpression(node.initializer);
11886+
}
11887+
else {
11888+
// <Elem attr /> is sugar for <Elem attr={true} />
11889+
exprType = booleanType;
11890+
}
11891+
1188211892
// Look up the corresponding property for this attribute
1188311893
if (elementAttributesType === emptyObjectType && isUnhyphenatedJsxName(node.name.text)) {
1188411894
// If there is no 'props' property, you may not have non-"data-" attributes
@@ -11902,15 +11912,6 @@ namespace ts {
1190211912
}
1190311913
}
1190411914

11905-
let exprType: Type;
11906-
if (node.initializer) {
11907-
exprType = checkExpression(node.initializer);
11908-
}
11909-
else {
11910-
// <Elem attr /> is sugar for <Elem attr={true} />
11911-
exprType = booleanType;
11912-
}
11913-
1191411915
if (correspondingPropType) {
1191511916
checkTypeAssignableTo(exprType, correspondingPropType, node);
1191611917
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
//// [tests/cases/compiler/reactImportDropped.ts] ////
2+
3+
//// [react.d.ts]
4+
5+
export = React;
6+
export as namespace React;
7+
8+
declare namespace React {
9+
10+
function createClass(spec: any): ClassicComponentClass;
11+
12+
interface ClassicComponentClass {
13+
new (props?: any): ClassicComponentClass;
14+
}
15+
}
16+
17+
declare global {
18+
namespace JSX {
19+
interface ElementAttributesProperty { }
20+
}
21+
}
22+
23+
24+
//// [TabBar.js]
25+
export default React.createClass({
26+
render() {
27+
return (
28+
null
29+
);
30+
}
31+
});
32+
33+
//// [NavigationView.js]
34+
import TabBar from '../../components/TabBar';
35+
import {layout} from '../../utils/theme'; // <- DO NOT DROP this import
36+
const x = <TabBar height={layout.footerHeight} />;
37+
38+
39+
//// [TabBar.js]
40+
export default React.createClass({
41+
render() {
42+
return (null);
43+
}
44+
});
45+
//// [NavigationView.js]
46+
import TabBar from '../../components/TabBar';
47+
import { layout } from '../../utils/theme'; // <- DO NOT DROP this import
48+
const x = React.createElement(TabBar, { height: layout.footerHeight });
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
=== tests/cases/compiler/react.d.ts ===
2+
3+
export = React;
4+
>React : Symbol(React, Decl(react.d.ts, 2, 26))
5+
6+
export as namespace React;
7+
>React : Symbol(React, Decl(react.d.ts, 1, 15))
8+
9+
declare namespace React {
10+
>React : Symbol(React, Decl(react.d.ts, 2, 26))
11+
12+
function createClass(spec: any): ClassicComponentClass;
13+
>createClass : Symbol(createClass, Decl(react.d.ts, 4, 25))
14+
>spec : Symbol(spec, Decl(react.d.ts, 6, 25))
15+
>ClassicComponentClass : Symbol(ClassicComponentClass, Decl(react.d.ts, 6, 59))
16+
17+
interface ClassicComponentClass {
18+
>ClassicComponentClass : Symbol(ClassicComponentClass, Decl(react.d.ts, 6, 59))
19+
20+
new (props?: any): ClassicComponentClass;
21+
>props : Symbol(props, Decl(react.d.ts, 9, 13))
22+
>ClassicComponentClass : Symbol(ClassicComponentClass, Decl(react.d.ts, 6, 59))
23+
}
24+
}
25+
26+
declare global {
27+
>global : Symbol(global, Decl(react.d.ts, 11, 1))
28+
29+
namespace JSX {
30+
>JSX : Symbol(JSX, Decl(react.d.ts, 13, 16))
31+
32+
interface ElementAttributesProperty { }
33+
>ElementAttributesProperty : Symbol(ElementAttributesProperty, Decl(react.d.ts, 14, 19))
34+
}
35+
}
36+
37+
38+
=== tests/cases/compiler/src/components/TabBar.js ===
39+
export default React.createClass({
40+
>React.createClass : Symbol(React.createClass, Decl(react.d.ts, 4, 25))
41+
>React : Symbol(React, Decl(react.d.ts, 1, 15))
42+
>createClass : Symbol(React.createClass, Decl(react.d.ts, 4, 25))
43+
44+
render() {
45+
>render : Symbol(render, Decl(TabBar.js, 0, 34))
46+
47+
return (
48+
null
49+
);
50+
}
51+
});
52+
53+
=== tests/cases/compiler/src/modules/navigation/NavigationView.js ===
54+
import TabBar from '../../components/TabBar';
55+
>TabBar : Symbol(TabBar, Decl(NavigationView.js, 0, 6))
56+
57+
import {layout} from '../../utils/theme'; // <- DO NOT DROP this import
58+
>layout : Symbol(layout, Decl(NavigationView.js, 1, 8))
59+
60+
const x = <TabBar height={layout.footerHeight} />;
61+
>x : Symbol(x, Decl(NavigationView.js, 2, 5))
62+
>TabBar : Symbol(TabBar, Decl(NavigationView.js, 0, 6))
63+
>height : Symbol(layout)
64+
>layout : Symbol(layout, Decl(NavigationView.js, 1, 8))
65+
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
=== tests/cases/compiler/react.d.ts ===
2+
3+
export = React;
4+
>React : typeof React
5+
6+
export as namespace React;
7+
>React : typeof React
8+
9+
declare namespace React {
10+
>React : typeof React
11+
12+
function createClass(spec: any): ClassicComponentClass;
13+
>createClass : (spec: any) => ClassicComponentClass
14+
>spec : any
15+
>ClassicComponentClass : ClassicComponentClass
16+
17+
interface ClassicComponentClass {
18+
>ClassicComponentClass : ClassicComponentClass
19+
20+
new (props?: any): ClassicComponentClass;
21+
>props : any
22+
>ClassicComponentClass : ClassicComponentClass
23+
}
24+
}
25+
26+
declare global {
27+
>global : any
28+
29+
namespace JSX {
30+
>JSX : any
31+
32+
interface ElementAttributesProperty { }
33+
>ElementAttributesProperty : ElementAttributesProperty
34+
}
35+
}
36+
37+
38+
=== tests/cases/compiler/src/components/TabBar.js ===
39+
export default React.createClass({
40+
>React.createClass({ render() { return ( null ); }}) : React.ClassicComponentClass
41+
>React.createClass : (spec: any) => React.ClassicComponentClass
42+
>React : typeof React
43+
>createClass : (spec: any) => React.ClassicComponentClass
44+
>{ render() { return ( null ); }} : { render(): any; }
45+
46+
render() {
47+
>render : () => any
48+
49+
return (
50+
>( null ) : null
51+
52+
null
53+
>null : null
54+
55+
);
56+
}
57+
});
58+
59+
=== tests/cases/compiler/src/modules/navigation/NavigationView.js ===
60+
import TabBar from '../../components/TabBar';
61+
>TabBar : React.ClassicComponentClass
62+
63+
import {layout} from '../../utils/theme'; // <- DO NOT DROP this import
64+
>layout : any
65+
66+
const x = <TabBar height={layout.footerHeight} />;
67+
>x : any
68+
><TabBar height={layout.footerHeight} /> : any
69+
>TabBar : React.ClassicComponentClass
70+
>height : any
71+
>layout.footerHeight : any
72+
>layout : any
73+
>footerHeight : any
74+
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
//@module: es6
2+
//@moduleResolution: node
3+
//@target: es6
4+
//@noImplicitAny: false
5+
//@allowSyntheticDefaultImports: true
6+
//@allowJs: true
7+
//@jsx: react
8+
//@outDir: "build"
9+
10+
//@filename: react.d.ts
11+
export = React;
12+
export as namespace React;
13+
14+
declare namespace React {
15+
16+
function createClass(spec: any): ClassicComponentClass;
17+
18+
interface ClassicComponentClass {
19+
new (props?: any): ClassicComponentClass;
20+
}
21+
}
22+
23+
declare global {
24+
namespace JSX {
25+
interface ElementAttributesProperty { }
26+
}
27+
}
28+
29+
30+
//@filename: src/components/TabBar.js
31+
export default React.createClass({
32+
render() {
33+
return (
34+
null
35+
);
36+
}
37+
});
38+
39+
//@filename: src/modules/navigation/NavigationView.js
40+
import TabBar from '../../components/TabBar';
41+
import {layout} from '../../utils/theme'; // <- DO NOT DROP this import
42+
const x = <TabBar height={layout.footerHeight} />;

0 commit comments

Comments
 (0)