Skip to content

Commit 44ade7a

Browse files
committed
added jsx: "local" mode to support render systems like VueJS
1 parent 4a90614 commit 44ade7a

File tree

7 files changed

+63
-22
lines changed

7 files changed

+63
-22
lines changed

lib/tsserverlibrary.d.ts

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
1-
/*! *****************************************************************************
2-
Copyright (c) Microsoft Corporation. All rights reserved.
3-
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
4-
this file except in compliance with the License. You may obtain a copy of the
5-
License at http://www.apache.org/licenses/LICENSE-2.0
6-
7-
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
8-
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
9-
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
10-
MERCHANTABLITY OR NON-INFRINGEMENT.
11-
12-
See the Apache Version 2.0 License for specific language governing permissions
13-
and limitations under the License.
14-
***************************************************************************** */
15-
1+
/*! *****************************************************************************
2+
Copyright (c) Microsoft Corporation. All rights reserved.
3+
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
4+
this file except in compliance with the License. You may obtain a copy of the
5+
License at http://www.apache.org/licenses/LICENSE-2.0
6+
7+
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
8+
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
9+
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
10+
MERCHANTABLITY OR NON-INFRINGEMENT.
11+
12+
See the Apache Version 2.0 License for specific language governing permissions
13+
and limitations under the License.
14+
***************************************************************************** */
15+
1616
/// <reference path="../../src/server/types.d.ts" />
1717
/// <reference types="node" />
1818
declare namespace ts {
@@ -3509,6 +3509,7 @@ declare namespace ts.server.protocol {
35093509
type None = "None";
35103510
type Preserve = "Preserve";
35113511
type React = "React";
3512+
type Local = "Local";
35123513
}
35133514
type JsxEmit = JsxEmit.None | JsxEmit.Preserve | JsxEmit.React;
35143515
namespace ModuleKind {

src/compiler/checker.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11346,6 +11346,23 @@ namespace ts {
1134611346
}
1134711347
}
1134811348

11349+
// if JSX mode is local, check that createElement is in scope
11350+
if (compilerOptions.jsx === JsxEmit.Local) {
11351+
const createElementRefError = Diagnostics.Cannot_find_name_0;
11352+
const createElementFnName = "createElement";
11353+
const createElementSym = resolveName(node.tagName, createElementFnName, SymbolFlags.Value, createElementRefError, createElementFnName);
11354+
if (createElementSym) {
11355+
// Mark local symbol as referenced here because it might not have been marked
11356+
// if jsx emit was not simple as there wont be error being emitted
11357+
createElementSym.isReferenced = true;
11358+
11359+
// If createElement symbol is alias, mark it as refereced
11360+
if (createElementSym.flags & SymbolFlags.Alias && !isConstEnumOrConstEnumOnlyModule(resolveAlias(createElementSym))) {
11361+
markAliasSymbolAsReferenced(createElementSym);
11362+
}
11363+
}
11364+
}
11365+
1134911366
const targetAttributesType = getJsxElementAttributesType(node);
1135011367

1135111368
const nameTable = createMap<boolean>();

src/compiler/commandLineParser.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,8 @@ namespace ts {
6767
name: "jsx",
6868
type: createMap({
6969
"preserve": JsxEmit.Preserve,
70-
"react": JsxEmit.React
70+
"react": JsxEmit.React,
71+
"local": JsxEmit.Local
7172
}),
7273
paramType: Diagnostics.KIND,
7374
description: Diagnostics.Specify_JSX_code_generation_Colon_preserve_or_react,

src/compiler/factory.ts

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1628,7 +1628,19 @@ namespace ts {
16281628
return react;
16291629
}
16301630

1631-
export function createReactCreateElement(reactNamespace: string, tagName: Expression, props: Expression, children: Expression[], parentElement: JsxOpeningLikeElement, location: TextRange): LeftHandSideExpression {
1631+
function createSynthCreateElement(parent: JsxOpeningLikeElement) {
1632+
// To ensure the emit resolver can properly resolve the namespace, we need to
1633+
// treat this identifier as if it were a source tree node by clearing the `Synthesized`
1634+
// flag and setting a parent node.
1635+
const react = createIdentifier("createElement");
1636+
react.flags &= ~NodeFlags.Synthesized;
1637+
// Set the parent that is in parse tree
1638+
// this makes sure that parent chain is intact for checker to traverse complete scope tree
1639+
react.parent = getParseTreeNode(parent);
1640+
return react;
1641+
}
1642+
1643+
export function createReactCreateElement(reactNamespace: string, tagName: Expression, props: Expression, children: Expression[], parentElement: JsxOpeningLikeElement, location: TextRange, jsxEmit: JsxEmit): LeftHandSideExpression {
16321644
const argumentsList = [tagName];
16331645
if (props) {
16341646
argumentsList.push(props);
@@ -1650,12 +1662,20 @@ namespace ts {
16501662
}
16511663
}
16521664

1665+
if (jsxEmit === JsxEmit.Local) {
1666+
return createCall(
1667+
createSynthCreateElement(parentElement),
1668+
/*typeArguments*/ undefined,
1669+
argumentsList,
1670+
location);
1671+
}
1672+
16531673
return createCall(
16541674
createPropertyAccess(
16551675
createReactNamespace(reactNamespace, parentElement),
16561676
"createElement"
16571677
),
1658-
/*typeArguments*/ undefined,
1678+
/*typeArguments*/ undefined,
16591679
argumentsList,
16601680
location
16611681
);

src/compiler/transformer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ namespace ts {
112112

113113
transformers.push(transformTypeScript);
114114

115-
if (jsx === JsxEmit.React) {
115+
if (jsx === JsxEmit.React || jsx === JsxEmit.Local) {
116116
transformers.push(transformJsx);
117117
}
118118

src/compiler/transformers/jsx.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,14 +112,15 @@ namespace ts {
112112
objectProperties = singleOrUndefined(segments)
113113
|| createAssignHelper(currentSourceFile.externalHelpersModuleName, segments);
114114
}
115-
115+
116116
const element = createReactCreateElement(
117117
compilerOptions.reactNamespace,
118118
tagName,
119119
objectProperties,
120120
filter(map(children, transformJsxChildToExpression), isDefined),
121121
node,
122-
location
122+
location,
123+
compilerOptions.jsx
123124
);
124125

125126
if (isChild) {

src/compiler/types.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3131,7 +3131,8 @@ namespace ts {
31313131
export const enum JsxEmit {
31323132
None = 0,
31333133
Preserve = 1,
3134-
React = 2
3134+
React = 2,
3135+
Local = 3
31353136
}
31363137

31373138
export const enum NewLineKind {

0 commit comments

Comments
 (0)