Optimize jsx spreads of object expressions (#12557)
This commit is contained in:
parent
0d6063f1b9
commit
ed90f17978
@ -316,13 +316,20 @@ You can set \`throwIfNamespace: false\` to bypass this warning.`,
|
||||
}
|
||||
}
|
||||
|
||||
function convertAttribute(node) {
|
||||
const value = convertAttributeValue(node.value || t.booleanLiteral(true));
|
||||
|
||||
function accumulateAttribute(array, node) {
|
||||
if (t.isJSXSpreadAttribute(node)) {
|
||||
return t.spreadElement(node.argument);
|
||||
const arg = node.argument;
|
||||
// Collect properties into props array if spreading object expression
|
||||
if (t.isObjectExpression(arg)) {
|
||||
array.push(...arg.properties);
|
||||
} else {
|
||||
array.push(t.spreadElement(arg));
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
const value = convertAttributeValue(node.value || t.booleanLiteral(true));
|
||||
|
||||
if (t.isStringLiteral(value) && !t.isJSXExpressionContainer(node.value)) {
|
||||
value.value = value.value.replace(/\n\s+/g, " ");
|
||||
|
||||
@ -340,7 +347,8 @@ You can set \`throwIfNamespace: false\` to bypass this warning.`,
|
||||
node.name = t.stringLiteral(node.name.name);
|
||||
}
|
||||
|
||||
return t.inherits(t.objectProperty(node.name, value), node);
|
||||
array.push(t.inherits(t.objectProperty(node.name, value), node));
|
||||
return array;
|
||||
}
|
||||
|
||||
function buildChildrenProperty(children) {
|
||||
@ -420,7 +428,7 @@ You can set \`throwIfNamespace: false\` to bypass this warning.`,
|
||||
// Builds props for React.jsx. This function adds children into the props
|
||||
// and ensures that props is always an object
|
||||
function buildJSXOpeningElementAttributes(attribs, file, children) {
|
||||
const props = attribs.map(convertAttribute);
|
||||
const props = attribs.reduce(accumulateAttribute, []);
|
||||
|
||||
// In React.jsx, children is no longer a separate argument, but passed in
|
||||
// through the argument object
|
||||
@ -530,38 +538,36 @@ You can set \`throwIfNamespace: false\` to bypass this warning.`,
|
||||
found[name] = true;
|
||||
}
|
||||
|
||||
props.push(convertAttribute(attr));
|
||||
accumulateAttribute(props, attr);
|
||||
}
|
||||
|
||||
return props.length > 0 ? t.objectExpression(props) : t.nullLiteral();
|
||||
}
|
||||
|
||||
let props = [];
|
||||
const objs = [];
|
||||
const props = attribs.reduce(accumulateAttribute, []);
|
||||
|
||||
for (const attr of attribs) {
|
||||
if (useSpread || !t.isJSXSpreadAttribute(attr)) {
|
||||
props.push(convertAttribute(attr));
|
||||
} else {
|
||||
if (props.length) {
|
||||
objs.push(t.objectExpression(props));
|
||||
props = [];
|
||||
if (!useSpread) {
|
||||
// Convert syntax to use multiple objects instead of spread
|
||||
let start = 0;
|
||||
props.forEach((prop, i) => {
|
||||
if (t.isSpreadElement(prop)) {
|
||||
if (i > start) {
|
||||
objs.push(t.objectExpression(props.slice(start, i)));
|
||||
}
|
||||
objs.push(prop.argument);
|
||||
start = i + 1;
|
||||
}
|
||||
objs.push(attr.argument);
|
||||
});
|
||||
if (props.length > start) {
|
||||
objs.push(t.objectExpression(props.slice(start)));
|
||||
}
|
||||
}
|
||||
|
||||
if (!props.length && !objs.length) {
|
||||
return t.nullLiteral();
|
||||
}
|
||||
|
||||
if (useSpread) {
|
||||
return props.length > 0 ? t.objectExpression(props) : t.nullLiteral();
|
||||
}
|
||||
|
||||
if (props.length) {
|
||||
} else if (props.length) {
|
||||
objs.push(t.objectExpression(props));
|
||||
props = [];
|
||||
}
|
||||
|
||||
if (!objs.length) {
|
||||
return t.nullLiteral();
|
||||
}
|
||||
|
||||
if (objs.length === 1) {
|
||||
|
||||
@ -0,0 +1,7 @@
|
||||
<p prop prop>text</p>;
|
||||
|
||||
<p {...{prop, prop}}>text</p>;
|
||||
|
||||
<p prop {...{prop}}>text</p>;
|
||||
|
||||
<p {...{prop}} prop>text</p>;
|
||||
@ -0,0 +1,29 @@
|
||||
import { jsx as _jsx } from "react/jsx-runtime";
|
||||
|
||||
/*#__PURE__*/
|
||||
_jsx("p", {
|
||||
prop: true,
|
||||
prop: true,
|
||||
children: "text"
|
||||
});
|
||||
|
||||
/*#__PURE__*/
|
||||
_jsx("p", {
|
||||
prop,
|
||||
prop,
|
||||
children: "text"
|
||||
});
|
||||
|
||||
/*#__PURE__*/
|
||||
_jsx("p", {
|
||||
prop: true,
|
||||
prop,
|
||||
children: "text"
|
||||
});
|
||||
|
||||
/*#__PURE__*/
|
||||
_jsx("p", {
|
||||
prop,
|
||||
prop: true,
|
||||
children: "text"
|
||||
});
|
||||
@ -0,0 +1,7 @@
|
||||
<p {...props}>text</p>;
|
||||
|
||||
<div {...props}>{contents}</div>;
|
||||
|
||||
<img alt="" {...{src, title}} />;
|
||||
|
||||
<blockquote {...{cite}}>{items}</blockquote>;
|
||||
@ -0,0 +1,24 @@
|
||||
import { jsx as _jsx } from "react/jsx-runtime";
|
||||
|
||||
/*#__PURE__*/
|
||||
_jsx("p", { ...props,
|
||||
children: "text"
|
||||
});
|
||||
|
||||
/*#__PURE__*/
|
||||
_jsx("div", { ...props,
|
||||
children: contents
|
||||
});
|
||||
|
||||
/*#__PURE__*/
|
||||
_jsx("img", {
|
||||
alt: "",
|
||||
src,
|
||||
title
|
||||
});
|
||||
|
||||
/*#__PURE__*/
|
||||
_jsx("blockquote", {
|
||||
cite,
|
||||
children: items
|
||||
});
|
||||
11
packages/babel-plugin-transform-react-jsx/test/fixtures/react/avoids-spread/input.js
vendored
Normal file
11
packages/babel-plugin-transform-react-jsx/test/fixtures/react/avoids-spread/input.js
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
<E {...props} last />;
|
||||
|
||||
<E first {...props} />;
|
||||
|
||||
<E {...pre} {...suf} />;
|
||||
|
||||
<E first {...pre} mid {...suf} />;
|
||||
|
||||
<E {...pre} mid {...suf} last />;
|
||||
|
||||
<E {...pre} mid1 mid2 {...suf} />;
|
||||
32
packages/babel-plugin-transform-react-jsx/test/fixtures/react/avoids-spread/output.js
vendored
Normal file
32
packages/babel-plugin-transform-react-jsx/test/fixtures/react/avoids-spread/output.js
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
/*#__PURE__*/
|
||||
React.createElement(E, babelHelpers.extends({}, props, {
|
||||
last: true
|
||||
}));
|
||||
|
||||
/*#__PURE__*/
|
||||
React.createElement(E, babelHelpers.extends({
|
||||
first: true
|
||||
}, props));
|
||||
|
||||
/*#__PURE__*/
|
||||
React.createElement(E, babelHelpers.extends({}, pre, suf));
|
||||
|
||||
/*#__PURE__*/
|
||||
React.createElement(E, babelHelpers.extends({
|
||||
first: true
|
||||
}, pre, {
|
||||
mid: true
|
||||
}, suf));
|
||||
|
||||
/*#__PURE__*/
|
||||
React.createElement(E, babelHelpers.extends({}, pre, {
|
||||
mid: true
|
||||
}, suf, {
|
||||
last: true
|
||||
}));
|
||||
|
||||
/*#__PURE__*/
|
||||
React.createElement(E, babelHelpers.extends({}, pre, {
|
||||
mid1: true,
|
||||
mid2: true
|
||||
}, suf));
|
||||
7
packages/babel-plugin-transform-react-jsx/test/fixtures/react/duplicate-props/input.js
vendored
Normal file
7
packages/babel-plugin-transform-react-jsx/test/fixtures/react/duplicate-props/input.js
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
<p prop prop>text</p>;
|
||||
|
||||
<p {...{prop, prop}}>text</p>;
|
||||
|
||||
<p prop {...{prop}}>text</p>;
|
||||
|
||||
<p {...{prop}} prop>text</p>;
|
||||
23
packages/babel-plugin-transform-react-jsx/test/fixtures/react/duplicate-props/output.js
vendored
Normal file
23
packages/babel-plugin-transform-react-jsx/test/fixtures/react/duplicate-props/output.js
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
/*#__PURE__*/
|
||||
React.createElement("p", {
|
||||
prop: true,
|
||||
prop: true
|
||||
}, "text");
|
||||
|
||||
/*#__PURE__*/
|
||||
React.createElement("p", {
|
||||
prop,
|
||||
prop
|
||||
}, "text");
|
||||
|
||||
/*#__PURE__*/
|
||||
React.createElement("p", {
|
||||
prop: true,
|
||||
prop
|
||||
}, "text");
|
||||
|
||||
/*#__PURE__*/
|
||||
React.createElement("p", {
|
||||
prop,
|
||||
prop: true
|
||||
}, "text");
|
||||
7
packages/babel-plugin-transform-react-jsx/test/fixtures/react/flattens-spread/input.js
vendored
Normal file
7
packages/babel-plugin-transform-react-jsx/test/fixtures/react/flattens-spread/input.js
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
<p {...props}>text</p>;
|
||||
|
||||
<div {...props}>{contents}</div>;
|
||||
|
||||
<img alt="" {...{src, title}} />;
|
||||
|
||||
<blockquote {...{cite}}>{items}</blockquote>;
|
||||
17
packages/babel-plugin-transform-react-jsx/test/fixtures/react/flattens-spread/output.js
vendored
Normal file
17
packages/babel-plugin-transform-react-jsx/test/fixtures/react/flattens-spread/output.js
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
/*#__PURE__*/
|
||||
React.createElement("p", props, "text");
|
||||
|
||||
/*#__PURE__*/
|
||||
React.createElement("div", props, contents);
|
||||
|
||||
/*#__PURE__*/
|
||||
React.createElement("img", {
|
||||
alt: "",
|
||||
src,
|
||||
title
|
||||
});
|
||||
|
||||
/*#__PURE__*/
|
||||
React.createElement("blockquote", {
|
||||
cite
|
||||
}, items);
|
||||
Loading…
x
Reference in New Issue
Block a user