Skip to content

Commit 0f78f53

Browse files
authored
Merge pull request #12967 from Microsoft/fix12749
Do not transform JSX tag names for ES3
2 parents f034022 + 14e05cd commit 0f78f53

File tree

5 files changed

+192
-0
lines changed

5 files changed

+192
-0
lines changed

src/compiler/transformers/es5.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,20 @@ namespace ts {
99
* @param context Context and state information for the transformation.
1010
*/
1111
export function transformES5(context: TransformationContext) {
12+
const compilerOptions = context.getCompilerOptions();
13+
14+
// enable emit notification only if using --jsx preserve
15+
let previousOnEmitNode: (emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void) => void;
16+
let noSubstitution: boolean[];
17+
if (compilerOptions.jsx === JsxEmit.Preserve) {
18+
previousOnEmitNode = context.onEmitNode;
19+
context.onEmitNode = onEmitNode;
20+
context.enableEmitNotification(SyntaxKind.JsxOpeningElement);
21+
context.enableEmitNotification(SyntaxKind.JsxClosingElement);
22+
context.enableEmitNotification(SyntaxKind.JsxSelfClosingElement);
23+
noSubstitution = [];
24+
}
25+
1226
const previousOnSubstituteNode = context.onSubstituteNode;
1327
context.onSubstituteNode = onSubstituteNode;
1428
context.enableSubstitution(SyntaxKind.PropertyAccessExpression);
@@ -24,13 +38,35 @@ namespace ts {
2438
return node;
2539
}
2640

41+
/**
42+
* Called by the printer just before a node is printed.
43+
*
44+
* @param node The node to be printed.
45+
*/
46+
function onEmitNode(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void) {
47+
switch (node.kind) {
48+
case SyntaxKind.JsxOpeningElement:
49+
case SyntaxKind.JsxClosingElement:
50+
case SyntaxKind.JsxSelfClosingElement:
51+
const tagName = (<JsxOpeningElement | JsxClosingElement | JsxSelfClosingElement>node).tagName;
52+
noSubstitution[getOriginalNodeId(tagName)] = true;
53+
break;
54+
}
55+
56+
previousOnEmitNode(emitContext, node, emitCallback);
57+
}
58+
2759
/**
2860
* Hooks node substitutions.
2961
*
3062
* @param emitContext The context for the emitter.
3163
* @param node The node to substitute.
3264
*/
3365
function onSubstituteNode(emitContext: EmitContext, node: Node) {
66+
if (node.id && noSubstitution && noSubstitution[node.id]) {
67+
return previousOnSubstituteNode(emitContext, node);
68+
}
69+
3470
node = previousOnSubstituteNode(emitContext, node);
3571
if (isPropertyAccessExpression(node)) {
3672
return substitutePropertyAccessExpression(node);
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
//// [tests/cases/compiler/jsxViaImport.2.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+
export default class extends React.Component<any, {}> {
13+
}
14+
}
15+
16+
//// [consumer.tsx]
17+
/// <reference path="component.d.ts" />
18+
import BaseComponent from 'BaseComponent';
19+
class TestComponent extends React.Component<any, {}> {
20+
render() {
21+
return <BaseComponent />;
22+
}
23+
}
24+
25+
26+
//// [consumer.jsx]
27+
"use strict";
28+
var __extends = (this && this.__extends) || function (d, b) {
29+
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
30+
function __() { this.constructor = d; }
31+
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
32+
};
33+
/// <reference path="component.d.ts" />
34+
var BaseComponent_1 = require("BaseComponent");
35+
var TestComponent = (function (_super) {
36+
__extends(TestComponent, _super);
37+
function TestComponent() {
38+
return _super.apply(this, arguments) || this;
39+
}
40+
TestComponent.prototype.render = function () {
41+
return <BaseComponent_1.default />;
42+
};
43+
return TestComponent;
44+
}(React.Component));
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
=== tests/cases/compiler/consumer.tsx ===
2+
/// <reference path="component.d.ts" />
3+
import BaseComponent from 'BaseComponent';
4+
>BaseComponent : Symbol(BaseComponent, Decl(consumer.tsx, 1, 6))
5+
6+
class TestComponent extends React.Component<any, {}> {
7+
>TestComponent : Symbol(TestComponent, Decl(consumer.tsx, 1, 42))
8+
>React.Component : Symbol(React.Component, Decl(component.d.ts, 4, 22))
9+
>React : Symbol(React, Decl(component.d.ts, 3, 1))
10+
>Component : Symbol(React.Component, Decl(component.d.ts, 4, 22))
11+
12+
render() {
13+
>render : Symbol(TestComponent.render, Decl(consumer.tsx, 2, 54))
14+
15+
return <BaseComponent />;
16+
>BaseComponent : Symbol(BaseComponent, Decl(consumer.tsx, 1, 6))
17+
}
18+
}
19+
20+
=== tests/cases/compiler/component.d.ts ===
21+
22+
declare module JSX {
23+
>JSX : Symbol(JSX, Decl(component.d.ts, 0, 0))
24+
25+
interface ElementAttributesProperty { props; }
26+
>ElementAttributesProperty : Symbol(ElementAttributesProperty, Decl(component.d.ts, 1, 20))
27+
>props : Symbol(ElementAttributesProperty.props, Decl(component.d.ts, 2, 39))
28+
}
29+
declare module React {
30+
>React : Symbol(React, Decl(component.d.ts, 3, 1))
31+
32+
class Component<T, U> { }
33+
>Component : Symbol(Component, Decl(component.d.ts, 4, 22))
34+
>T : Symbol(T, Decl(component.d.ts, 5, 18))
35+
>U : Symbol(U, Decl(component.d.ts, 5, 20))
36+
}
37+
declare module "BaseComponent" {
38+
export default class extends React.Component<any, {}> {
39+
>React.Component : Symbol(React.Component, Decl(component.d.ts, 4, 22))
40+
>React : Symbol(React, Decl(component.d.ts, 3, 1))
41+
>Component : Symbol(React.Component, Decl(component.d.ts, 4, 22))
42+
}
43+
}
44+
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
=== tests/cases/compiler/consumer.tsx ===
2+
/// <reference path="component.d.ts" />
3+
import BaseComponent from 'BaseComponent';
4+
>BaseComponent : typeof BaseComponent
5+
6+
class TestComponent extends React.Component<any, {}> {
7+
>TestComponent : TestComponent
8+
>React.Component : React.Component<any, {}>
9+
>React : typeof React
10+
>Component : typeof React.Component
11+
12+
render() {
13+
>render : () => any
14+
15+
return <BaseComponent />;
16+
><BaseComponent /> : any
17+
>BaseComponent : typeof BaseComponent
18+
}
19+
}
20+
21+
=== tests/cases/compiler/component.d.ts ===
22+
23+
declare module JSX {
24+
>JSX : any
25+
26+
interface ElementAttributesProperty { props; }
27+
>ElementAttributesProperty : ElementAttributesProperty
28+
>props : any
29+
}
30+
declare module React {
31+
>React : typeof React
32+
33+
class Component<T, U> { }
34+
>Component : Component<T, U>
35+
>T : T
36+
>U : U
37+
}
38+
declare module "BaseComponent" {
39+
export default class extends React.Component<any, {}> {
40+
>React.Component : React.Component<any, {}>
41+
>React : typeof React
42+
>Component : typeof React.Component
43+
}
44+
}
45+
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+
export default class extends React.Component<any, {}> {
13+
}
14+
}
15+
16+
//@filename: consumer.tsx
17+
/// <reference path="component.d.ts" />
18+
import BaseComponent from 'BaseComponent';
19+
class TestComponent extends React.Component<any, {}> {
20+
render() {
21+
return <BaseComponent />;
22+
}
23+
}

0 commit comments

Comments
 (0)