diff --git a/packages/babel-plugin-transform-react-jsx/src/create-plugin.ts b/packages/babel-plugin-transform-react-jsx/src/create-plugin.ts index 3e3a93963030..1b23ae5c769a 100644 --- a/packages/babel-plugin-transform-react-jsx/src/create-plugin.ts +++ b/packages/babel-plugin-transform-react-jsx/src/create-plugin.ts @@ -39,6 +39,15 @@ const get = (pass: PluginPass, name: string) => const set = (pass: PluginPass, name: string, v: any) => pass.set(`@babel/plugin-react-jsx/${name}`, v); +function hasProto(node: t.ObjectExpression) { + return node.properties.some( + value => + t.isObjectProperty(value, { computed: false, shorthand: false }) && + (t.isIdentifier(value.key, { name: "__proto__" }) || + t.isStringLiteral(value.key, { value: "__proto__" })), + ); +} + export interface Options { filter?: (node: t.Node, pass: PluginPass) => boolean; importSource?: string; @@ -422,7 +431,7 @@ You can set \`throwIfNamespace: false\` to bypass this warning.`, if (t.isJSXSpreadAttribute(attribute.node)) { const arg = attribute.node.argument; // Collect properties into props array if spreading object expression - if (t.isObjectExpression(arg)) { + if (t.isObjectExpression(arg) && !hasProto(arg)) { array.push(...arg.properties); } else { array.push(t.spreadElement(arg)); @@ -718,7 +727,17 @@ You can set \`throwIfNamespace: false\` to bypass this warning.`, } if (objs.length === 1) { - return objs[0]; + if ( + !( + t.isSpreadElement(props[0]) && + // If an object expression is spread element's argument + // it is very likely to contain __proto__ and we should stop + // optimizing spread element + t.isObjectExpression(props[0].argument) + ) + ) { + return objs[0]; + } } // looks like we have multiple objects @@ -755,7 +774,12 @@ You can set \`throwIfNamespace: false\` to bypass this warning.`, accumulateAttribute(props, attr); } - return props.length === 1 && t.isSpreadElement(props[0]) + return props.length === 1 && + t.isSpreadElement(props[0]) && + // If an object expression is spread element's argument + // it is very likely to contain __proto__ and we should stop + // optimizing spread element + !t.isObjectExpression(props[0].argument) ? props[0].argument : props.length > 0 ? t.objectExpression(props) diff --git a/packages/babel-plugin-transform-react-jsx/test/fixtures/react-automatic/flattens-spread/input.js b/packages/babel-plugin-transform-react-jsx/test/fixtures/react-automatic/flattens-spread/input.js index 7cf92a69c605..24d4257e21b4 100644 --- a/packages/babel-plugin-transform-react-jsx/test/fixtures/react-automatic/flattens-spread/input.js +++ b/packages/babel-plugin-transform-react-jsx/test/fixtures/react-automatic/flattens-spread/input.js @@ -2,6 +2,10 @@
{items}; + +; + +
;
diff --git a/packages/babel-plugin-transform-react-jsx/test/fixtures/react-automatic/flattens-spread/output.mjs b/packages/babel-plugin-transform-react-jsx/test/fixtures/react-automatic/flattens-spread/output.mjs
index 738dcc4e9e95..1612ddc01cf0 100644
--- a/packages/babel-plugin-transform-react-jsx/test/fixtures/react-automatic/flattens-spread/output.mjs
+++ b/packages/babel-plugin-transform-react-jsx/test/fixtures/react-automatic/flattens-spread/output.mjs
@@ -14,7 +14,8 @@ _jsx("div", { ...props,
_jsx("img", {
alt: "",
src,
- title
+ title,
+ __proto__
});
/*#__PURE__*/
@@ -22,3 +23,13 @@ _jsx("blockquote", {
cite,
children: items
});
+
+/*#__PURE__*/
+_jsx("pre", {
+ ["__proto__"]: null
+});
+
+/*#__PURE__*/
+_jsx("code", {
+ [__proto__]: null
+});
diff --git a/packages/babel-plugin-transform-react-jsx/test/fixtures/react-automatic/handle-spread-with-proto/input.js b/packages/babel-plugin-transform-react-jsx/test/fixtures/react-automatic/handle-spread-with-proto/input.js
new file mode 100644
index 000000000000..4d745e96c31f
--- /dev/null
+++ b/packages/babel-plugin-transform-react-jsx/test/fixtures/react-automatic/handle-spread-with-proto/input.js
@@ -0,0 +1,3 @@
+text
; + +{items}; + +; + +
;
diff --git a/packages/babel-plugin-transform-react-jsx/test/fixtures/react/flattens-spread/output.js b/packages/babel-plugin-transform-react-jsx/test/fixtures/react/flattens-spread/output.js
index 25b234ea3b58..59b3fe96530b 100644
--- a/packages/babel-plugin-transform-react-jsx/test/fixtures/react/flattens-spread/output.js
+++ b/packages/babel-plugin-transform-react-jsx/test/fixtures/react/flattens-spread/output.js
@@ -8,10 +8,21 @@ React.createElement("div", props, contents);
React.createElement("img", {
alt: "",
src,
- title
+ title,
+ __proto__
});
/*#__PURE__*/
React.createElement("blockquote", {
cite
}, items);
+
+/*#__PURE__*/
+React.createElement("pre", {
+ ["__proto__"]: null
+});
+
+/*#__PURE__*/
+React.createElement("code", {
+ [__proto__]: null
+});
diff --git a/packages/babel-plugin-transform-react-jsx/test/fixtures/react/handle-spread-with-proto-babel-7/input.js b/packages/babel-plugin-transform-react-jsx/test/fixtures/react/handle-spread-with-proto-babel-7/input.js
new file mode 100644
index 000000000000..4d745e96c31f
--- /dev/null
+++ b/packages/babel-plugin-transform-react-jsx/test/fixtures/react/handle-spread-with-proto-babel-7/input.js
@@ -0,0 +1,3 @@
+text
; + +text
; + +