Skip to content

Commit 3952486

Browse files
JLHwungbabel-bot
andauthored
Reverts "Re-use common JSX element transform for <>...</>" (#15355)
* Reverts "Re-use common JSX element transform for <>...</>" * add a regression test * fix Babel 8 test error * Update fixtures (Windows) * disable the regression test on Babel 8 Co-authored-by: Babel Bot <babel-bot@users.noreply.github.com>
1 parent 0f68471 commit 3952486

11 files changed

Lines changed: 82 additions & 40 deletions

File tree

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
/*#__PURE__*/babelHelpers.jsx(React.Fragment, {}, void 0, /*#__PURE__*/babelHelpers.jsx("span", {}), /*#__PURE__*/babelHelpers.jsx("div", {}));
1+
/*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/babelHelpers.jsx("span", {}), /*#__PURE__*/babelHelpers.jsx("div", {}));

packages/babel-plugin-transform-react-jsx-development/test/fixtures/linux/auto-import-dev/output.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
var _jsxFileName = "<CWD>/packages/babel-plugin-transform-react-jsx-development/test/fixtures/linux/auto-import-dev/input.js";
2-
import { Fragment as _Fragment } from "react/jsx-dev-runtime";
32
import { jsxDEV as _jsxDEV } from "react/jsx-dev-runtime";
43
import { createElement as _createElement } from "react";
4+
import { Fragment as _Fragment } from "react/jsx-dev-runtime";
55
var x = /*#__PURE__*/_jsxDEV(_Fragment, {
66
children: /*#__PURE__*/_jsxDEV("div", {
77
children: [/*#__PURE__*/_jsxDEV("div", {}, "1", false, {

packages/babel-plugin-transform-react-jsx-development/test/fixtures/windows/auto-import-dev-windows/output.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
var _jsxFileName = "<CWD>\\packages\\babel-plugin-transform-react-jsx-development\\test\\fixtures\\windows\\auto-import-dev-windows\\input.js";
2-
import { Fragment as _Fragment } from "react/jsx-dev-runtime";
32
import { jsxDEV as _jsxDEV } from "react/jsx-dev-runtime";
43
import { createElement as _createElement } from "react";
4+
import { Fragment as _Fragment } from "react/jsx-dev-runtime";
55
var x = /*#__PURE__*/_jsxDEV(_Fragment, {
66
children: /*#__PURE__*/_jsxDEV("div", {
77
children: [/*#__PURE__*/_jsxDEV("div", {}, "1", false, {

packages/babel-plugin-transform-react-jsx/src/create-plugin.ts

Lines changed: 64 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import type {
1212
Identifier,
1313
JSXAttribute,
1414
JSXElement,
15+
JSXFragment,
1516
JSXOpeningElement,
1617
JSXSpreadAttribute,
1718
MemberExpression,
@@ -71,6 +72,9 @@ export default function createPlugin({
7172

7273
throwIfNamespace = true,
7374

75+
// TODO (Babel 8): It should throw if this option is used with the automatic runtime
76+
filter,
77+
7478
runtime: RUNTIME_DEFAULT = process.env.BABEL_8_BREAKING
7579
? "automatic"
7680
: development
@@ -276,24 +280,17 @@ You can set \`throwIfNamespace: false\` to bypass this warning.`,
276280
// },
277281
},
278282

279-
JSXFragment(path, file) {
280-
// <>...</> -> <React.Fragment>...</React.Fragment>
281-
282-
const frag = memberExpressionToJSX(get(file, "id/fragment")());
283+
JSXFragment: {
284+
exit(path, file) {
285+
let callExpr;
286+
if (get(file, "runtime") === "classic") {
287+
callExpr = buildCreateElementFragmentCall(path, file);
288+
} else {
289+
callExpr = buildJSXFragmentCall(path, file);
290+
}
283291

284-
path.replaceWith(
285-
t.inherits(
286-
t.jsxElement(
287-
t.inherits(
288-
t.jsxOpeningElement(frag, []),
289-
path.node.openingFragment,
290-
),
291-
t.jsxClosingElement(t.cloneNode(frag)),
292-
path.node.children,
293-
),
294-
path.node,
295-
),
296-
);
292+
path.replaceWith(t.inherits(callExpr, path.node));
293+
},
297294
},
298295

299296
JSXElement: {
@@ -603,6 +600,56 @@ You can set \`throwIfNamespace: false\` to bypass this warning.`,
603600
return t.objectExpression(props);
604601
}
605602

603+
// Builds JSX Fragment <></> into
604+
// Production: React.jsx(type, arguments)
605+
// Development: React.jsxDEV(type, { children })
606+
function buildJSXFragmentCall(
607+
path: NodePath<JSXFragment>,
608+
file: PluginPass,
609+
) {
610+
const args = [get(file, "id/fragment")()];
611+
612+
const children = t.react.buildChildren(path.node);
613+
614+
args.push(
615+
t.objectExpression(
616+
children.length > 0
617+
? [
618+
buildChildrenProperty(
619+
//@ts-expect-error The children here contains JSXSpreadChild,
620+
// which will be thrown later
621+
children,
622+
),
623+
]
624+
: [],
625+
),
626+
);
627+
628+
if (development) {
629+
args.push(
630+
path.scope.buildUndefinedNode(),
631+
t.booleanLiteral(children.length > 1),
632+
);
633+
}
634+
635+
return call(file, children.length > 1 ? "jsxs" : "jsx", args);
636+
}
637+
638+
// Builds JSX Fragment <></> into
639+
// React.createElement(React.Fragment, null, ...children)
640+
function buildCreateElementFragmentCall(
641+
path: NodePath<JSXFragment>,
642+
file: PluginPass,
643+
) {
644+
if (filter && !filter(path.node, file)) return;
645+
646+
return call(file, "createElement", [
647+
get(file, "id/fragment")(),
648+
t.nullLiteral(),
649+
...t.react.buildChildren(path.node),
650+
]);
651+
}
652+
606653
// Builds JSX into:
607654
// Production: React.createElement(type, arguments, children)
608655
// Development: React.createElement(type, arguments, children, source, self)
@@ -806,22 +853,6 @@ function toMemberExpression(id: string): Identifier | MemberExpression {
806853
);
807854
}
808855

809-
function memberExpressionToJSX(
810-
expr: t.Node,
811-
): t.JSXMemberExpression | t.JSXIdentifier {
812-
switch (expr.type) {
813-
case "Identifier":
814-
return t.jsxIdentifier(expr.name);
815-
case "MemberExpression":
816-
return t.jsxMemberExpression(
817-
memberExpressionToJSX(expr.object),
818-
memberExpressionToJSX(expr.property) as t.JSXIdentifier,
819-
);
820-
default:
821-
throw new Error("Internal error: unknown member expression type");
822-
}
823-
}
824-
825856
function makeSource(path: NodePath, state: PluginPass) {
826857
const location = path.node.loc;
827858
if (!location) {

packages/babel-plugin-transform-react-jsx/test/fixtures/autoImport/auto-import-react-source-type-module/output.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import { Fragment as _Fragment } from "react/jsx-runtime";
21
import { jsx as _jsx } from "react/jsx-runtime";
32
import { createElement as _createElement } from "react";
43
import { jsxs as _jsxs } from "react/jsx-runtime";
4+
import { Fragment as _Fragment } from "react/jsx-runtime";
55
var x = /*#__PURE__*/_jsx(_Fragment, {
66
children: /*#__PURE__*/_jsxs("div", {
77
children: [/*#__PURE__*/_jsx("div", {}, "1"), /*#__PURE__*/_jsx("div", {

packages/babel-plugin-transform-react-jsx/test/fixtures/react-automatic/does-not-add-source-self-automatic/output.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import { Fragment as _Fragment } from "react/jsx-runtime";
21
import { jsx as _jsx } from "react/jsx-runtime";
32
import { createElement as _createElement } from "react";
43
import { jsxs as _jsxs } from "react/jsx-runtime";
4+
import { Fragment as _Fragment } from "react/jsx-runtime";
55
var x = /*#__PURE__*/_jsx(_Fragment, {
66
children: /*#__PURE__*/_jsxs("div", {
77
children: [/*#__PURE__*/_jsx("div", {}, "1"), /*#__PURE__*/_jsx("div", {
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { Fragment as _Fragment } from "react/jsx-runtime";
21
import { jsx as _jsx } from "react/jsx-runtime";
2+
import { Fragment as _Fragment } from "react/jsx-runtime";
33
var x = /*#__PURE__*/_jsx(_Fragment, {
44
children: /*#__PURE__*/_jsx("div", {})
55
});

packages/babel-plugin-transform-react-jsx/test/fixtures/react-automatic/should-allow-nested-fragments/output.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { Fragment as _Fragment } from "react/jsx-runtime";
21
import { jsx as _jsx } from "react/jsx-runtime";
2+
import { Fragment as _Fragment } from "react/jsx-runtime";
33
import { jsxs as _jsxs } from "react/jsx-runtime";
44
/*#__PURE__*/_jsx("div", {
55
children: /*#__PURE__*/_jsxs(_Fragment, {
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<>Test</>;
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"BABEL_8_BREAKING": false,
3+
"plugins": [
4+
[
5+
"transform-react-jsx",
6+
{ "pragma": "m", "pragmaFrag": "'['", "runtime": "classic" }
7+
]
8+
]
9+
}

0 commit comments

Comments
 (0)