Mark hoisted react constant elements as #__PURE__ (#7372)

This commit is contained in:
Mateusz Burzyński 2018-02-21 18:58:56 +01:00 committed by GitHub
parent d75a6b8468
commit d283324f8a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
42 changed files with 180 additions and 57 deletions

View File

@ -4,7 +4,9 @@ function action() {
return _action.apply(this, arguments); return _action.apply(this, arguments);
} }
var _ref = React.createElement(Contact, { var _ref =
/*#__PURE__*/
React.createElement(Contact, {
title: title title: title
}); });

View File

@ -8,6 +8,9 @@
"keywords": [ "keywords": [
"babel-plugin" "babel-plugin"
], ],
"dependencies": {
"@babel/helper-annotate-as-pure": "7.0.0-beta.40"
},
"peerDependencies": { "peerDependencies": {
"@babel/core": "7.0.0-beta.40" "@babel/core": "7.0.0-beta.40"
}, },

View File

@ -1,4 +1,5 @@
import { types as t } from "@babel/core"; import { types as t } from "@babel/core";
import annotateAsPure from "@babel/helper-annotate-as-pure";
export default function transformReactConstantElement(api, options) { export default function transformReactConstantElement(api, options) {
const { allowMutablePropsOnTags } = options; const { allowMutablePropsOnTags } = options;
@ -101,7 +102,11 @@ export default function transformReactConstantElement(api, options) {
path.traverse(immutabilityVisitor, state); path.traverse(immutabilityVisitor, state);
if (state.isImmutable) { if (state.isImmutable) {
path.hoist(); const hoisted = path.hoist();
if (hoisted) {
annotateAsPure(hoisted);
}
} }
}, },
}, },

View File

@ -1,10 +1,14 @@
var _ref = <div>child</div>; var _ref =
/*#__PURE__*/
<div>child</div>;
const AppItem = () => { const AppItem = () => {
return _ref; return _ref;
}; };
var _ref2 = <div> var _ref2 =
/*#__PURE__*/
<div>
<p>Parent</p> <p>Parent</p>
<AppItem /> <AppItem />
</div>; </div>;

View File

@ -1,6 +1,10 @@
var _ref2 = <div>child</div>; var _ref2 =
/*#__PURE__*/
<div>child</div>;
var _ref3 = <p>Parent</p>; var _ref3 =
/*#__PURE__*/
<p>Parent</p>;
(function () { (function () {
class App extends React.Component { class App extends React.Component {
@ -13,7 +17,9 @@ var _ref3 = <p>Parent</p>;
const AppItem = () => { const AppItem = () => {
return _ref2; return _ref2;
}, },
_ref = <div> _ref =
/*#__PURE__*/
<div>
{_ref3} {_ref3}
<AppItem /> <AppItem />
</div>; </div>;

View File

@ -1,13 +1,19 @@
var _ref = <div>child</div>; var _ref =
/*#__PURE__*/
<div>child</div>;
var _ref3 = <p>Parent</p>; var _ref3 =
/*#__PURE__*/
<p>Parent</p>;
(function () { (function () {
const AppItem = () => { const AppItem = () => {
return _ref; return _ref;
}; };
var _ref2 = <div> var _ref2 =
/*#__PURE__*/
<div>
{_ref3} {_ref3}
<AppItem /> <AppItem />
</div>; </div>;

View File

@ -5,12 +5,16 @@ export default class App extends React.Component {
} }
var _ref2 = <div>child</div>; var _ref2 =
/*#__PURE__*/
<div>child</div>;
const AppItem = () => { const AppItem = () => {
return _ref2; return _ref2;
}, },
_ref = <div> _ref =
/*#__PURE__*/
<div>
<p>Parent</p> <p>Parent</p>
<AppItem /> <AppItem />
</div>; </div>;

View File

@ -1,4 +1,6 @@
var _ref = <span />; var _ref =
/*#__PURE__*/
<span />;
var Foo = React.createClass({ var Foo = React.createClass({
render: function () { render: function () {

View File

@ -1,6 +1,8 @@
import React from 'react'; // Regression test for https://github.com/babel/babel/issues/5552 import React from 'react'; // Regression test for https://github.com/babel/babel/issues/5552
var _ref = <div />; var _ref =
/*#__PURE__*/
<div />;
class BugReport extends React.Component { class BugReport extends React.Component {
constructor(...args) { constructor(...args) {

View File

@ -1,9 +1,13 @@
import React from 'react'; import React from 'react';
import Loader from 'loader'; import Loader from 'loader';
var _ref = <Loader className="full-height" />; var _ref =
/*#__PURE__*/
<Loader className="full-height" />;
var _ref2 = <Loader className="p-y-5" />; var _ref2 =
/*#__PURE__*/
<Loader className="p-y-5" />;
const errorComesHere = () => _ref, const errorComesHere = () => _ref,
thisWorksFine = () => _ref2; thisWorksFine = () => _ref2;

View File

@ -1,6 +1,8 @@
var Foo = require("Foo"); var Foo = require("Foo");
var _ref = <Foo />; var _ref =
/*#__PURE__*/
<Foo />;
function render() { function render() {
return _ref; return _ref;

View File

@ -1,6 +1,10 @@
var _ref = <b></b>; var _ref =
/*#__PURE__*/
<b></b>;
var _ref2 = <span></span>; var _ref2 =
/*#__PURE__*/
<span></span>;
function render() { function render() {
var children = _ref; var children = _ref;

View File

@ -4,11 +4,15 @@ const Parent = ({}) => _ref;
export default Parent; export default Parent;
var _ref2 = <div className="child"> var _ref2 =
/*#__PURE__*/
<div className="child">
ChildTextContent ChildTextContent
</div>; </div>;
let Child = () => _ref2, let Child = () => _ref2,
_ref = <div className="parent"> _ref =
/*#__PURE__*/
<div className="parent">
<Child /> <Child />
</div>; </div>;

View File

@ -1,6 +1,8 @@
function render() { function render() {
const bar = "bar", const bar = "bar",
_ref = <foo bar={bar} />, _ref =
/*#__PURE__*/
<foo bar={bar} />,
renderFoo = () => _ref; renderFoo = () => _ref;
return renderFoo(); return renderFoo();
@ -10,7 +12,9 @@ function render() {
const bar = "bar", const bar = "bar",
renderFoo = () => _ref2, renderFoo = () => _ref2,
baz = "baz", baz = "baz",
_ref2 = <foo bar={bar} baz={baz} />; _ref2 =
/*#__PURE__*/
<foo bar={bar} baz={baz} />;
return renderFoo(); return renderFoo();
} }

View File

@ -1,7 +1,9 @@
function render() { function render() {
var title = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; var title = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
var _ref = <Component title={title} />; var _ref =
/*#__PURE__*/
<Component title={title} />;
return () => _ref; return () => _ref;
} }

View File

@ -1,6 +1,8 @@
function render(Component) { function render(Component) {
var text = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '', var text = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '',
_ref = <Component text={text} />; _ref =
/*#__PURE__*/
<Component text={text} />;
return function () { return function () {
return _ref; return _ref;

View File

@ -6,7 +6,9 @@ const Parent = ({}) => _ref;
export default Parent; export default Parent;
var _ref2 = <div className="child"> var _ref2 =
/*#__PURE__*/
<div className="child">
ChildTextContent ChildTextContent
</div>; </div>;
@ -14,6 +16,8 @@ let Child = () => _ref2;
Child = HOC(Child); Child = HOC(Child);
var _ref = <div className="parent"> var _ref =
/*#__PURE__*/
<div className="parent">
<Child /> <Child />
</div>; </div>;

View File

@ -1,5 +1,7 @@
function render(text) { function render(text) {
var _ref = <foo>{text}</foo>; var _ref =
/*#__PURE__*/
<foo>{text}</foo>;
return function () { return function () {
return _ref; return _ref;
@ -9,7 +11,9 @@ function render(text) {
var Foo2 = require("Foo"); var Foo2 = require("Foo");
function createComponent(text) { function createComponent(text) {
var _ref2 = <Foo2>{text}</Foo2>; var _ref2 =
/*#__PURE__*/
<Foo2>{text}</Foo2>;
return function render() { return function render() {
return _ref2; return _ref2;

View File

@ -1,4 +1,6 @@
var _ref = <div foo={notDeclared}></div>; var _ref =
/*#__PURE__*/
<div foo={notDeclared}></div>;
var Foo = React.createClass({ var Foo = React.createClass({
render: function render() { render: function render() {

View File

@ -1,10 +1,14 @@
var _ref = <foo />; var _ref =
/*#__PURE__*/
<foo />;
function render() { function render() {
return _ref; return _ref;
} }
var _ref2 = <div className="foo"><input type="checkbox" checked={true} /></div>; var _ref2 =
/*#__PURE__*/
<div className="foo"><input type="checkbox" checked={true} /></div>;
function render() { function render() {
return _ref2; return _ref2;

View File

@ -2,7 +2,9 @@ var REACT_ELEMENT_TYPE;
function _jsx(type, props, key, children) { if (!REACT_ELEMENT_TYPE) { REACT_ELEMENT_TYPE = typeof Symbol === "function" && Symbol.for && Symbol.for("react.element") || 0xeac7; } var defaultProps = type && type.defaultProps; var childrenLength = arguments.length - 3; if (!props && childrenLength !== 0) { props = { children: void 0 }; } if (props && defaultProps) { for (var propName in defaultProps) { if (props[propName] === void 0) { props[propName] = defaultProps[propName]; } } } else if (!props) { props = defaultProps || {}; } if (childrenLength === 1) { props.children = children; } else if (childrenLength > 1) { var childArray = new Array(childrenLength); for (var i = 0; i < childrenLength; i++) { childArray[i] = arguments[i + 3]; } props.children = childArray; } return { $$typeof: REACT_ELEMENT_TYPE, type: type, key: key === undefined ? null : '' + key, ref: null, props: props, _owner: null }; } function _jsx(type, props, key, children) { if (!REACT_ELEMENT_TYPE) { REACT_ELEMENT_TYPE = typeof Symbol === "function" && Symbol.for && Symbol.for("react.element") || 0xeac7; } var defaultProps = type && type.defaultProps; var childrenLength = arguments.length - 3; if (!props && childrenLength !== 0) { props = { children: void 0 }; } if (props && defaultProps) { for (var propName in defaultProps) { if (props[propName] === void 0) { props[propName] = defaultProps[propName]; } } } else if (!props) { props = defaultProps || {}; } if (childrenLength === 1) { props.children = children; } else if (childrenLength > 1) { var childArray = new Array(childrenLength); for (var i = 0; i < childrenLength; i++) { childArray[i] = arguments[i + 3]; } props.children = childArray; } return { $$typeof: REACT_ELEMENT_TYPE, type: type, key: key === undefined ? null : '' + key, ref: null, props: props, _owner: null }; }
var _ref = _jsx("foo", {}); var _ref =
/*#__PURE__*/
_jsx("foo", {});
function render() { function render() {
return _ref; return _ref;
@ -11,7 +13,9 @@ function render() {
function render() { function render() {
var text = getText(); var text = getText();
var _ref2 = _jsx("foo", {}, void 0, text); var _ref2 =
/*#__PURE__*/
_jsx("foo", {}, void 0, text);
return function () { return function () {
return _ref2; return _ref2;

View File

@ -1,7 +1,9 @@
function render() { function render() {
var text = getText(); var text = getText();
var _ref = <foo>{text}</foo>; var _ref =
/*#__PURE__*/
<foo>{text}</foo>;
return function () { return function () {
return _ref; return _ref;

View File

@ -1,7 +1,9 @@
function render() { function render() {
this.component = "div"; this.component = "div";
var _ref = <this.component />; var _ref =
/*#__PURE__*/
<this.component />;
return () => _ref; return () => _ref;
} }

View File

@ -1,10 +1,14 @@
var _ref = <span>Sub Component</span>; var _ref =
/*#__PURE__*/
<span>Sub Component</span>;
class Component extends React.Component { class Component extends React.Component {
constructor(...args) { constructor(...args) {
var _temp; var _temp;
var _ref2 = <this.subComponent />; var _ref2 =
/*#__PURE__*/
<this.subComponent />;
return _temp = super(...args), this.subComponent = () => _ref, this.render = () => _ref2, _temp; return _temp = super(...args), this.subComponent = () => _ref, this.render = () => _ref2, _temp;
} }

View File

@ -1,10 +1,14 @@
var _ref = <span>Sub Component</span>; var _ref =
/*#__PURE__*/
<span>Sub Component</span>;
const els = { const els = {
subComponent: () => _ref subComponent: () => _ref
}; };
var _ref2 = <els.subComponent />; var _ref2 =
/*#__PURE__*/
<els.subComponent />;
class Component extends React.Component { class Component extends React.Component {
constructor(...args) { constructor(...args) {

View File

@ -1,6 +1,8 @@
function fn(Component, obj) { function fn(Component, obj) {
var data = obj.data, var data = obj.data,
_ref = <Component prop={data} />; _ref =
/*#__PURE__*/
<Component prop={data} />;
return () => _ref; return () => _ref;
} }

View File

@ -3,7 +3,9 @@ function render(_ref) {
className = _ref.className, className = _ref.className,
id = _ref.id; id = _ref.id;
var _ref2 = <Component text={text} className={className} id={id} />; var _ref2 =
/*#__PURE__*/
<Component text={text} className={className} id={id} />;
return () => _ref2; return () => _ref2;
} }

View File

@ -4,7 +4,9 @@ function render(_ref) {
id = _ref.id, id = _ref.id,
props = babelHelpers.objectWithoutProperties(_ref, ["text", "className", "id"]); props = babelHelpers.objectWithoutProperties(_ref, ["text", "className", "id"]);
var _ref2 = <Component text={text} className={className} id={id} />; var _ref2 =
/*#__PURE__*/
<Component text={text} className={className} id={id} />;
// intentionally ignoring props // intentionally ignoring props
return () => _ref2; return () => _ref2;

View File

@ -1,7 +1,9 @@
function render(_ref) { function render(_ref) {
let text = _ref.text; let text = _ref.text;
var _ref2 = <Component text={text} />; var _ref2 =
/*#__PURE__*/
<Component text={text} />;
return () => _ref2; return () => _ref2;
} }

View File

@ -1,5 +1,7 @@
function render(text) { function render(text) {
var _ref = <div>{text}</div>; var _ref =
/*#__PURE__*/
<div>{text}</div>;
return function () { return function () {
return _ref; return _ref;

View File

@ -1,5 +1,7 @@
function render(offset) { function render(offset) {
var _ref = <div tabIndex={offset + 1} />; var _ref =
/*#__PURE__*/
<div tabIndex={offset + 1} />;
return function () { return function () {
return _ref; return _ref;

View File

@ -1,6 +1,8 @@
const OFFSET = 3; const OFFSET = 3;
var _ref = <div tabIndex={OFFSET + 1} />; var _ref =
/*#__PURE__*/
<div tabIndex={OFFSET + 1} />;
var Foo = React.createClass({ var Foo = React.createClass({
render: function () { render: function () {

View File

@ -1,6 +1,8 @@
import Intl from 'react-intl'; import Intl from 'react-intl';
var _ref = <Intl.FormattedMessage id="someMessage.foo" defaultMessage={"Some text, " + "and some more too. {someValue}"} description="A test message for babel." values={{ var _ref =
/*#__PURE__*/
<Intl.FormattedMessage id="someMessage.foo" defaultMessage={"Some text, " + "and some more too. {someValue}"} description="A test message for babel." values={{
someValue: "A value." someValue: "A value."
}} />; }} />;

View File

@ -1,4 +1,6 @@
var _ref = <FormattedMessage id="someMessage.foo" defaultMessage={"Some text, " + "and some more too. {someValue}"} description="A test message for babel." values={{ var _ref =
/*#__PURE__*/
<FormattedMessage id="someMessage.foo" defaultMessage={"Some text, " + "and some more too. {someValue}"} description="A test message for babel." values={{
someValue: "A value." someValue: "A value."
}} />; }} />;

View File

@ -1,4 +1,6 @@
var _ref = <div data-text={"Some text, " + "and some more too."} />; var _ref =
/*#__PURE__*/
<div data-text={"Some text, " + "and some more too."} />;
var Foo = React.createClass({ var Foo = React.createClass({
render: function () { render: function () {

View File

@ -1,7 +1,9 @@
function render(text) { function render(text) {
text += "yes"; text += "yes";
var _ref = <div>{text}</div>; var _ref =
/*#__PURE__*/
<div>{text}</div>;
return function () { return function () {
return _ref; return _ref;

View File

@ -7,4 +7,6 @@ class A {
export default class B {} export default class B {}
var _ref = React.createElement(B, null); var _ref =
/*#__PURE__*/
React.createElement(B, null);

View File

@ -7,4 +7,6 @@ class A {
export class B {} export class B {}
var _ref = React.createElement(B, null); var _ref =
/*#__PURE__*/
React.createElement(B, null);

View File

@ -1,4 +1,6 @@
var _ref = <div className="class-name"> var _ref =
/*#__PURE__*/
<div className="class-name">
Text Text
</div>; </div>;

View File

@ -1,6 +1,8 @@
function fn(Component) { function fn(Component) {
var data = "prop", var data = "prop",
_ref = <Component prop={data} />; _ref =
/*#__PURE__*/
<Component prop={data} />;
return () => _ref; return () => _ref;
} }

View File

@ -1,4 +1,6 @@
var _ref = <div className="navbar-header"> var _ref =
/*#__PURE__*/
<div className="navbar-header">
<a className="navbar-brand" href="/"> <a className="navbar-brand" href="/">
<img src="/img/logo/logo-96x36.png" /> <img src="/img/logo/logo-96x36.png" />
</a> </a>

View File

@ -206,10 +206,11 @@ export default class PathHoister {
// generate declaration and insert it to our point // generate declaration and insert it to our point
let uid = attachTo.scope.generateUidIdentifier("ref"); let uid = attachTo.scope.generateUidIdentifier("ref");
const declarator = t.variableDeclarator(uid, this.path.node); const declarator = t.variableDeclarator(uid, this.path.node);
const insertFn = this.attachAfter ? "insertAfter" : "insertBefore"; const insertFn = this.attachAfter ? "insertAfter" : "insertBefore";
attachTo[insertFn]([ const [attached] = attachTo[insertFn]([
attachTo.isVariableDeclarator() attachTo.isVariableDeclarator()
? declarator ? declarator
: t.variableDeclaration("var", [declarator]), : t.variableDeclaration("var", [declarator]),
@ -223,5 +224,9 @@ export default class PathHoister {
} }
this.path.replaceWith(t.cloneNode(uid)); this.path.replaceWith(t.cloneNode(uid));
return attachTo.isVariableDeclarator()
? attached.get("init")
: attached.get("declarations.0.init");
} }
} }