diff --git a/src/compiler/transformers/jsx.ts b/src/compiler/transformers/jsx.ts index 0766cfbbfcf..544275c6d20 100644 --- a/src/compiler/transformers/jsx.ts +++ b/src/compiler/transformers/jsx.ts @@ -208,33 +208,36 @@ namespace ts { let objectProperties: Expression; const keyAttr = find(node.attributes.properties, p => !!p.name && isIdentifier(p.name) && p.name.escapedText === "key") as JsxAttribute | undefined; const attrs = keyAttr ? filter(node.attributes.properties, p => p !== keyAttr) : node.attributes.properties; - if (attrs.length === 0) { - objectProperties = factory.createObjectLiteralExpression([]); - // When there are no attributes, React wants {} - } - else { + + let segments: Expression[] = []; + if (attrs.length) { // Map spans of JsxAttribute nodes into object literals and spans // of JsxSpreadAttribute nodes into expressions. - const segments = flatten( + segments = flatten( spanMap(attrs, isJsxSpreadAttribute, (attrs, isSpread) => isSpread ? map(attrs, transformJsxSpreadAttributeToExpression) : factory.createObjectLiteralExpression(map(attrs, transformJsxAttributeToObjectLiteralElement)) ) ); - if (children && children.length) { - const result = convertJsxChildrenToChildrenPropObject(children); - if (result) { - segments.push(result); - } - } - if (isJsxSpreadAttribute(attrs[0])) { // We must always emit at least one object literal before a spread // argument.factory.createObjectLiteral segments.unshift(factory.createObjectLiteralExpression()); } + } + if (children && children.length) { + const result = convertJsxChildrenToChildrenPropObject(children); + if (result) { + segments.push(result); + } + } + if (segments.length === 0) { + objectProperties = factory.createObjectLiteralExpression([]); + // When there are no attributes, React wants {} + } + else { // Either emit one big object literal (no spread attribs), or // a call to the __assign helper. objectProperties = singleOrUndefined(segments) || emitHelpers().createAssignHelper(segments); diff --git a/tests/baselines/reference/jsxJsxsCjsTransformChildren(jsx=react-jsx).js b/tests/baselines/reference/jsxJsxsCjsTransformChildren(jsx=react-jsx).js new file mode 100644 index 00000000000..bb94546b6f3 --- /dev/null +++ b/tests/baselines/reference/jsxJsxsCjsTransformChildren(jsx=react-jsx).js @@ -0,0 +1,13 @@ +//// [jsxJsxsCjsTransformChildren.tsx] +/// +const a =
text
; + +export {}; + + +//// [jsxJsxsCjsTransformChildren.js] +"use strict"; +exports.__esModule = true; +var jsx_runtime_1 = require("react/jsx-runtime"); +/// +var a = jsx_runtime_1.jsx("div", { children: "text" }, void 0); diff --git a/tests/baselines/reference/jsxJsxsCjsTransformChildren(jsx=react-jsx).symbols b/tests/baselines/reference/jsxJsxsCjsTransformChildren(jsx=react-jsx).symbols new file mode 100644 index 00000000000..9bdb4e987b5 --- /dev/null +++ b/tests/baselines/reference/jsxJsxsCjsTransformChildren(jsx=react-jsx).symbols @@ -0,0 +1,9 @@ +=== tests/cases/conformance/jsx/jsxs/jsxJsxsCjsTransformChildren.tsx === +/// +const a =
text
; +>a : Symbol(a, Decl(jsxJsxsCjsTransformChildren.tsx, 1, 5)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114)) + +export {}; + diff --git a/tests/baselines/reference/jsxJsxsCjsTransformChildren(jsx=react-jsx).types b/tests/baselines/reference/jsxJsxsCjsTransformChildren(jsx=react-jsx).types new file mode 100644 index 00000000000..716305916b6 --- /dev/null +++ b/tests/baselines/reference/jsxJsxsCjsTransformChildren(jsx=react-jsx).types @@ -0,0 +1,10 @@ +=== tests/cases/conformance/jsx/jsxs/jsxJsxsCjsTransformChildren.tsx === +/// +const a =
text
; +>a : JSX.Element +>
text
: JSX.Element +>div : any +>div : any + +export {}; + diff --git a/tests/baselines/reference/jsxJsxsCjsTransformChildren(jsx=react-jsxdev).js b/tests/baselines/reference/jsxJsxsCjsTransformChildren(jsx=react-jsxdev).js new file mode 100644 index 00000000000..227e714da14 --- /dev/null +++ b/tests/baselines/reference/jsxJsxsCjsTransformChildren(jsx=react-jsxdev).js @@ -0,0 +1,14 @@ +//// [jsxJsxsCjsTransformChildren.tsx] +/// +const a =
text
; + +export {}; + + +//// [jsxJsxsCjsTransformChildren.js] +"use strict"; +exports.__esModule = true; +var jsx_dev_runtime_1 = require("react/jsx-dev-runtime"); +var _jsxFileName = "tests/cases/conformance/jsx/jsxs/jsxJsxsCjsTransformChildren.tsx"; +/// +var a = jsx_dev_runtime_1.jsxDEV("div", { children: "text" }, void 0, false, { fileName: _jsxFileName, lineNumber: 2, columnNumber: 10 }, this); diff --git a/tests/baselines/reference/jsxJsxsCjsTransformChildren(jsx=react-jsxdev).symbols b/tests/baselines/reference/jsxJsxsCjsTransformChildren(jsx=react-jsxdev).symbols new file mode 100644 index 00000000000..9bdb4e987b5 --- /dev/null +++ b/tests/baselines/reference/jsxJsxsCjsTransformChildren(jsx=react-jsxdev).symbols @@ -0,0 +1,9 @@ +=== tests/cases/conformance/jsx/jsxs/jsxJsxsCjsTransformChildren.tsx === +/// +const a =
text
; +>a : Symbol(a, Decl(jsxJsxsCjsTransformChildren.tsx, 1, 5)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114)) + +export {}; + diff --git a/tests/baselines/reference/jsxJsxsCjsTransformChildren(jsx=react-jsxdev).types b/tests/baselines/reference/jsxJsxsCjsTransformChildren(jsx=react-jsxdev).types new file mode 100644 index 00000000000..716305916b6 --- /dev/null +++ b/tests/baselines/reference/jsxJsxsCjsTransformChildren(jsx=react-jsxdev).types @@ -0,0 +1,10 @@ +=== tests/cases/conformance/jsx/jsxs/jsxJsxsCjsTransformChildren.tsx === +/// +const a =
text
; +>a : JSX.Element +>
text
: JSX.Element +>div : any +>div : any + +export {}; + diff --git a/tests/cases/conformance/jsx/jsxs/jsxJsxsCjsTransformChildren.tsx b/tests/cases/conformance/jsx/jsxs/jsxJsxsCjsTransformChildren.tsx new file mode 100644 index 00000000000..e736b59c838 --- /dev/null +++ b/tests/cases/conformance/jsx/jsxs/jsxJsxsCjsTransformChildren.tsx @@ -0,0 +1,7 @@ +// @jsx: react-jsx,react-jsxdev +// @strict: true +// @module: commonjs +/// +const a =
text
; + +export {};