diff --git a/src/compiler/transformers/jsx.ts b/src/compiler/transformers/jsx.ts
index 9d4b1296620..905bfad32e0 100644
--- a/src/compiler/transformers/jsx.ts
+++ b/src/compiler/transformers/jsx.ts
@@ -26,12 +26,12 @@ namespace ts {
return currentFileState.filenameDeclaration.name;
}
- function getJsxFactoryCalleePrimitive(children: readonly JsxChild[] | undefined): "jsx" | "jsxs" | "jsxDEV" {
- return compilerOptions.jsx === JsxEmit.ReactJSXDev ? "jsxDEV" : children && children.length > 1 ? "jsxs" : "jsx";
+ function getJsxFactoryCalleePrimitive(childrenLength: number): "jsx" | "jsxs" | "jsxDEV" {
+ return compilerOptions.jsx === JsxEmit.ReactJSXDev ? "jsxDEV" : childrenLength > 1 ? "jsxs" : "jsx";
}
- function getJsxFactoryCallee(children: readonly JsxChild[] | undefined) {
- const type = getJsxFactoryCalleePrimitive(children);
+ function getJsxFactoryCallee(childrenLength: number) {
+ const type = getJsxFactoryCalleePrimitive(childrenLength);
return getImplicitImportForName(type);
}
@@ -191,8 +191,9 @@ namespace ts {
}
function convertJsxChildrenToChildrenPropObject(children: readonly JsxChild[]) {
- if (children.length === 1) {
- const result = transformJsxChildToExpression(children[0]);
+ const nonWhitespaceChildren = filter(children, c => !isJsxText(c) || !c.containsOnlyTriviaWhiteSpaces);
+ if (length(nonWhitespaceChildren) === 1) {
+ const result = transformJsxChildToExpression(nonWhitespaceChildren[0]);
return result && factory.createObjectLiteralExpression([
factory.createPropertyAssignment("children", result)
]);
@@ -243,16 +244,16 @@ namespace ts {
objectProperties = singleOrUndefined(segments) || emitHelpers().createAssignHelper(segments);
}
- return visitJsxOpeningLikeElementOrFragmentJSX(tagName, objectProperties, keyAttr, children, isChild, location);
+ return visitJsxOpeningLikeElementOrFragmentJSX(tagName, objectProperties, keyAttr, length(filter(children, c => !isJsxText(c) || !c.containsOnlyTriviaWhiteSpaces)), isChild, location);
}
- function visitJsxOpeningLikeElementOrFragmentJSX(tagName: Expression, objectProperties: Expression, keyAttr: JsxAttribute | undefined, children: readonly JsxChild[] | undefined, isChild: boolean, location: TextRange) {
+ function visitJsxOpeningLikeElementOrFragmentJSX(tagName: Expression, objectProperties: Expression, keyAttr: JsxAttribute | undefined, childrenLength: number, isChild: boolean, location: TextRange) {
const args: Expression[] = [tagName, objectProperties, !keyAttr ? factory.createVoidZero() : transformJsxAttributeInitializer(keyAttr.initializer)];
if (compilerOptions.jsx === JsxEmit.ReactJSXDev) {
const originalFile = getOriginalNode(currentSourceFile);
if (originalFile && isSourceFile(originalFile)) {
// isStaticChildren development flag
- args.push(children && children.length > 1 ? factory.createTrue() : factory.createFalse());
+ args.push(childrenLength > 1 ? factory.createTrue() : factory.createFalse());
// __source development flag
const lineCol = getLineAndCharacterOfPosition(originalFile, location.pos);
args.push(factory.createObjectLiteralExpression([
@@ -264,7 +265,7 @@ namespace ts {
args.push(factory.createThis());
}
}
- const element = setTextRange(factory.createCallExpression(getJsxFactoryCallee(children), /*typeArguments*/ undefined, args), location);
+ const element = setTextRange(factory.createCallExpression(getJsxFactoryCallee(childrenLength), /*typeArguments*/ undefined, args), location);
if (isChild) {
startOnNewLine(element);
@@ -335,7 +336,7 @@ namespace ts {
getImplicitJsxFragmentReference(),
childrenProps || factory.createObjectLiteralExpression([]),
/*keyAttr*/ undefined,
- children,
+ length(filter(children, c => !isJsxText(c) || !c.containsOnlyTriviaWhiteSpaces)),
isChild,
location
);
diff --git a/tests/baselines/reference/jsxJsxsCjsTransformNestedSelfClosingChild(jsx=react-jsx).js b/tests/baselines/reference/jsxJsxsCjsTransformNestedSelfClosingChild(jsx=react-jsx).js
new file mode 100644
index 00000000000..fd5ce7fede7
--- /dev/null
+++ b/tests/baselines/reference/jsxJsxsCjsTransformNestedSelfClosingChild(jsx=react-jsx).js
@@ -0,0 +1,31 @@
+//// [jsxJsxsCjsTransformNestedSelfClosingChild.tsx]
+///
+import type * as React from 'react';
+
+console.log(
+
+)
+
+console.log(
+
+)
+
+console.log(
+
+ {[1, 2].map(i =>
{i}
)}
+
+)
+
+//// [jsxJsxsCjsTransformNestedSelfClosingChild.js]
+"use strict";
+exports.__esModule = true;
+var jsx_runtime_js_1 = require("react/jsx-runtime.js");
+console.log(jsx_runtime_js_1.jsx("div", { children: jsx_runtime_js_1.jsx("div", {}, void 0) }, void 0));
+console.log(jsx_runtime_js_1.jsxs("div", { children: [jsx_runtime_js_1.jsx("div", {}, void 0),
+ jsx_runtime_js_1.jsx("div", {}, void 0)] }, void 0));
+console.log(jsx_runtime_js_1.jsx("div", { children: [1, 2].map(function (i) { return jsx_runtime_js_1.jsx("div", { children: i }, i); }) }, void 0));
diff --git a/tests/baselines/reference/jsxJsxsCjsTransformNestedSelfClosingChild(jsx=react-jsx).symbols b/tests/baselines/reference/jsxJsxsCjsTransformNestedSelfClosingChild(jsx=react-jsx).symbols
new file mode 100644
index 00000000000..a5b6314f416
--- /dev/null
+++ b/tests/baselines/reference/jsxJsxsCjsTransformNestedSelfClosingChild(jsx=react-jsx).symbols
@@ -0,0 +1,62 @@
+=== tests/cases/conformance/jsx/jsxs/jsxJsxsCjsTransformNestedSelfClosingChild.tsx ===
+///
+import type * as React from 'react';
+>React : Symbol(React, Decl(jsxJsxsCjsTransformNestedSelfClosingChild.tsx, 1, 11))
+
+console.log(
+>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
+>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
+>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
+
+
+>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114))
+
+
+>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114))
+
+
+>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114))
+
+)
+
+console.log(
+>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
+>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
+>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
+
+
+>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114))
+
+
+>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114))
+
+
+>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114))
+
+
+>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114))
+
+)
+
+console.log(
+>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
+>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
+>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
+
+
+>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114))
+
+ {[1, 2].map(i =>
{i}
)}
+>[1, 2].map : Symbol(Array.map, Decl(lib.es5.d.ts, --, --))
+>map : Symbol(Array.map, Decl(lib.es5.d.ts, --, --))
+>i : Symbol(i, Decl(jsxJsxsCjsTransformNestedSelfClosingChild.tsx, 18, 16))
+>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114))
+>key : Symbol(key, Decl(jsxJsxsCjsTransformNestedSelfClosingChild.tsx, 18, 25))
+>i : Symbol(i, Decl(jsxJsxsCjsTransformNestedSelfClosingChild.tsx, 18, 16))
+>i : Symbol(i, Decl(jsxJsxsCjsTransformNestedSelfClosingChild.tsx, 18, 16))
+>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114))
+
+
+>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114))
+
+)
diff --git a/tests/baselines/reference/jsxJsxsCjsTransformNestedSelfClosingChild(jsx=react-jsx).types b/tests/baselines/reference/jsxJsxsCjsTransformNestedSelfClosingChild(jsx=react-jsx).types
new file mode 100644
index 00000000000..07e78fc8dd5
--- /dev/null
+++ b/tests/baselines/reference/jsxJsxsCjsTransformNestedSelfClosingChild(jsx=react-jsx).types
@@ -0,0 +1,77 @@
+=== tests/cases/conformance/jsx/jsxs/jsxJsxsCjsTransformNestedSelfClosingChild.tsx ===
+///
+import type * as React from 'react';
+>React : typeof React
+
+console.log(
+>console.log( ) : void
+>console.log : (...data: any[]) => void
+>console : Console
+>log : (...data: any[]) => void
+
+
+>
: JSX.Element
+>div : any
+
+
+>
: JSX.Element
+>div : any
+
+
+>div : any
+
+)
+
+console.log(
+>console.log( ) : void
+>console.log : (...data: any[]) => void
+>console : Console
+>log : (...data: any[]) => void
+
+
+>
: JSX.Element
+>div : any
+
+
+>
: JSX.Element
+>div : any
+
+
+>
: JSX.Element
+>div : any
+
+
+>div : any
+
+)
+
+console.log(
+>console.log( ) : void
+>console.log : (...data: any[]) => void
+>console : Console
+>log : (...data: any[]) => void
+
+
+>
: JSX.Element
+>div : any
+
+ {[1, 2].map(i =>
{i}
)}
+>[1, 2].map(i =>
{i}
) : JSX.Element[]
+>[1, 2].map :
(callbackfn: (value: number, index: number, array: number[]) => U, thisArg?: any) => U[]
+>[1, 2] : number[]
+>1 : 1
+>2 : 2
+>map : (callbackfn: (value: number, index: number, array: number[]) => U, thisArg?: any) => U[]
+>i => {i}
: (i: number) => JSX.Element
+>i : number
+>{i}
: JSX.Element
+>div : any
+>key : number
+>i : number
+>i : number
+>div : any
+
+
+>div : any
+
+)
diff --git a/tests/baselines/reference/jsxJsxsCjsTransformNestedSelfClosingChild(jsx=react-jsxdev).js b/tests/baselines/reference/jsxJsxsCjsTransformNestedSelfClosingChild(jsx=react-jsxdev).js
new file mode 100644
index 00000000000..0e91bf32b15
--- /dev/null
+++ b/tests/baselines/reference/jsxJsxsCjsTransformNestedSelfClosingChild(jsx=react-jsxdev).js
@@ -0,0 +1,33 @@
+//// [jsxJsxsCjsTransformNestedSelfClosingChild.tsx]
+///
+import type * as React from 'react';
+
+console.log(
+
+)
+
+console.log(
+
+)
+
+console.log(
+
+ {[1, 2].map(i =>
{i}
)}
+
+)
+
+//// [jsxJsxsCjsTransformNestedSelfClosingChild.js]
+"use strict";
+var _this = this;
+exports.__esModule = true;
+var jsx_dev_runtime_js_1 = require("react/jsx-dev-runtime.js");
+var _jsxFileName = "tests/cases/conformance/jsx/jsxs/jsxJsxsCjsTransformNestedSelfClosingChild.tsx";
+console.log(jsx_dev_runtime_js_1.jsxDEV("div", { children: jsx_dev_runtime_js_1.jsxDEV("div", {}, void 0, false, { fileName: _jsxFileName, lineNumber: 6, columnNumber: 5 }, this) }, void 0, false, { fileName: _jsxFileName, lineNumber: 4, columnNumber: 13 }, this));
+console.log(jsx_dev_runtime_js_1.jsxDEV("div", { children: [jsx_dev_runtime_js_1.jsxDEV("div", {}, void 0, false, { fileName: _jsxFileName, lineNumber: 12, columnNumber: 5 }, this),
+ jsx_dev_runtime_js_1.jsxDEV("div", {}, void 0, false, { fileName: _jsxFileName, lineNumber: 13, columnNumber: 5 }, this)] }, void 0, true, { fileName: _jsxFileName, lineNumber: 10, columnNumber: 13 }, this));
+console.log(jsx_dev_runtime_js_1.jsxDEV("div", { children: [1, 2].map(function (i) { return jsx_dev_runtime_js_1.jsxDEV("div", { children: i }, i, false, { fileName: _jsxFileName, lineNumber: 19, columnNumber: 21 }, _this); }) }, void 0, false, { fileName: _jsxFileName, lineNumber: 17, columnNumber: 13 }, this));
diff --git a/tests/baselines/reference/jsxJsxsCjsTransformNestedSelfClosingChild(jsx=react-jsxdev).symbols b/tests/baselines/reference/jsxJsxsCjsTransformNestedSelfClosingChild(jsx=react-jsxdev).symbols
new file mode 100644
index 00000000000..a5b6314f416
--- /dev/null
+++ b/tests/baselines/reference/jsxJsxsCjsTransformNestedSelfClosingChild(jsx=react-jsxdev).symbols
@@ -0,0 +1,62 @@
+=== tests/cases/conformance/jsx/jsxs/jsxJsxsCjsTransformNestedSelfClosingChild.tsx ===
+///
+import type * as React from 'react';
+>React : Symbol(React, Decl(jsxJsxsCjsTransformNestedSelfClosingChild.tsx, 1, 11))
+
+console.log(
+>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
+>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
+>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
+
+
+>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114))
+
+
+>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114))
+
+
+>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114))
+
+)
+
+console.log(
+>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
+>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
+>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
+
+
+>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114))
+
+
+>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114))
+
+
+>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114))
+
+
+>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114))
+
+)
+
+console.log(
+>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
+>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
+>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
+
+
+>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114))
+
+ {[1, 2].map(i =>
{i}
)}
+>[1, 2].map : Symbol(Array.map, Decl(lib.es5.d.ts, --, --))
+>map : Symbol(Array.map, Decl(lib.es5.d.ts, --, --))
+>i : Symbol(i, Decl(jsxJsxsCjsTransformNestedSelfClosingChild.tsx, 18, 16))
+>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114))
+>key : Symbol(key, Decl(jsxJsxsCjsTransformNestedSelfClosingChild.tsx, 18, 25))
+>i : Symbol(i, Decl(jsxJsxsCjsTransformNestedSelfClosingChild.tsx, 18, 16))
+>i : Symbol(i, Decl(jsxJsxsCjsTransformNestedSelfClosingChild.tsx, 18, 16))
+>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114))
+
+
+>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114))
+
+)
diff --git a/tests/baselines/reference/jsxJsxsCjsTransformNestedSelfClosingChild(jsx=react-jsxdev).types b/tests/baselines/reference/jsxJsxsCjsTransformNestedSelfClosingChild(jsx=react-jsxdev).types
new file mode 100644
index 00000000000..07e78fc8dd5
--- /dev/null
+++ b/tests/baselines/reference/jsxJsxsCjsTransformNestedSelfClosingChild(jsx=react-jsxdev).types
@@ -0,0 +1,77 @@
+=== tests/cases/conformance/jsx/jsxs/jsxJsxsCjsTransformNestedSelfClosingChild.tsx ===
+///
+import type * as React from 'react';
+>React : typeof React
+
+console.log(
+>console.log( ) : void
+>console.log : (...data: any[]) => void
+>console : Console
+>log : (...data: any[]) => void
+
+
+>
: JSX.Element
+>div : any
+
+
+>
: JSX.Element
+>div : any
+
+
+>div : any
+
+)
+
+console.log(
+>console.log( ) : void
+>console.log : (...data: any[]) => void
+>console : Console
+>log : (...data: any[]) => void
+
+
+>
: JSX.Element
+>div : any
+
+
+>
: JSX.Element
+>div : any
+
+
+>
: JSX.Element
+>div : any
+
+
+>div : any
+
+)
+
+console.log(
+>console.log( ) : void
+>console.log : (...data: any[]) => void
+>console : Console
+>log : (...data: any[]) => void
+
+
+>
: JSX.Element
+>div : any
+
+ {[1, 2].map(i =>
{i}
)}
+>[1, 2].map(i =>
{i}
) : JSX.Element[]
+>[1, 2].map :
(callbackfn: (value: number, index: number, array: number[]) => U, thisArg?: any) => U[]
+>[1, 2] : number[]
+>1 : 1
+>2 : 2
+>map : (callbackfn: (value: number, index: number, array: number[]) => U, thisArg?: any) => U[]
+>i => {i}
: (i: number) => JSX.Element
+>i : number
+>{i}
: JSX.Element
+>div : any
+>key : number
+>i : number
+>i : number
+>div : any
+
+
+>div : any
+
+)
diff --git a/tests/cases/conformance/jsx/jsxs/jsxJsxsCjsTransformNestedSelfClosingChild.tsx b/tests/cases/conformance/jsx/jsxs/jsxJsxsCjsTransformNestedSelfClosingChild.tsx
new file mode 100644
index 00000000000..25f3fb738a7
--- /dev/null
+++ b/tests/cases/conformance/jsx/jsxs/jsxJsxsCjsTransformNestedSelfClosingChild.tsx
@@ -0,0 +1,24 @@
+// @jsx: react-jsx,react-jsxdev
+// @strict: true
+// @module: commonjs
+///
+import type * as React from 'react';
+
+console.log(
+
+)
+
+console.log(
+
+)
+
+console.log(
+
+ {[1, 2].map(i =>
{i}
)}
+
+)
\ No newline at end of file