Skip to content

Commit

Permalink
fix: skip flattening spread object with __proto__ (#14759)
Browse files Browse the repository at this point in the history
* fix: skip flattening spread object with __proto__

* update Babel 8 testcases

* fix single spread element optimization

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

Co-authored-by: Nicol貌 Ribaudo <nicolo.ribaudo@gmail.com>

* update test fixtures

Co-authored-by: Nicol貌 Ribaudo <nicolo.ribaudo@gmail.com>
  • Loading branch information
JLHwung and nicolo-ribaudo committed Jul 18, 2022
1 parent 770c22f commit ff6304b
Show file tree
Hide file tree
Showing 15 changed files with 117 additions and 7 deletions.
30 changes: 27 additions & 3 deletions packages/babel-plugin-transform-react-jsx/src/create-plugin.ts
Expand Up @@ -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;
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down
Expand Up @@ -2,6 +2,10 @@

<div {...props}>{contents}</div>;

<img alt="" {...{src, title}} />;
<img alt="" {...{src, title, __proto__}} />;

<blockquote {...{cite}}>{items}</blockquote>;

<pre {...{["__proto__"]: null }}></pre>;

<code {...{[__proto__]: null }}></code>;
Expand Up @@ -14,11 +14,22 @@ _jsx("div", { ...props,
_jsx("img", {
alt: "",
src,
title
title,
__proto__
});

/*#__PURE__*/
_jsx("blockquote", {
cite,
children: items
});

/*#__PURE__*/
_jsx("pre", {
["__proto__"]: null
});

/*#__PURE__*/
_jsx("code", {
[__proto__]: null
});
@@ -0,0 +1,3 @@
<p {...{__proto__: null}}>text</p>;

<div {...{"__proto__": null}}>{contents}</div>;
@@ -0,0 +1,15 @@
import { jsx as _jsx } from "react/jsx-runtime";

/*#__PURE__*/
_jsx("p", { ...{
__proto__: null
},
children: "text"
});

/*#__PURE__*/
_jsx("div", { ...{
"__proto__": null
},
children: contents
});
Expand Up @@ -2,6 +2,10 @@

<div {...props}>{contents}</div>;

<img alt="" {...{src, title}} />;
<img alt="" {...{src, title, __proto__}} />;

<blockquote {...{cite}}>{items}</blockquote>;

<pre {...{["__proto__"]: null }}></pre>;

<code {...{[__proto__]: null }}></code>;
Expand Up @@ -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
});
@@ -0,0 +1,3 @@
<p {...{__proto__: null}}>text</p>;

<div {...{"__proto__": null}}>{contents}</div>;
@@ -0,0 +1,3 @@
{
"BABEL_8_BREAKING": false
}
@@ -0,0 +1,9 @@
/*#__PURE__*/
React.createElement("p", babelHelpers.extends({
__proto__: null
}), "text");

/*#__PURE__*/
React.createElement("div", babelHelpers.extends({
"__proto__": null
}), contents);
@@ -0,0 +1,3 @@
<p {...{__proto__: null}}>text</p>;

<div {...{"__proto__": null}}>{contents}</div>;
@@ -0,0 +1,3 @@
{
"BABEL_8_BREAKING": true
}
@@ -0,0 +1,11 @@
/*#__PURE__*/
React.createElement("p", { ...{
__proto__: null
}
}, "text");

/*#__PURE__*/
React.createElement("div", { ...{
"__proto__": null
}
}, contents);
@@ -0,0 +1 @@
<p __proto__={null} class="bar">text</p>;
@@ -0,0 +1,5 @@
/*#__PURE__*/
React.createElement("p", {
__proto__: null,
class: "bar"
}, "text");

0 comments on commit ff6304b

Please sign in to comment.