Lazily initialize and cache constant JSX elements (#12967)

Co-authored-by: Justin Ridgewell <justin@ridgewell.name>
This commit is contained in:
Nicolò Ribaudo 2021-03-06 17:33:43 +01:00 committed by GitHub
parent d04842a700
commit 8dacf85859
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
72 changed files with 695 additions and 209 deletions

View File

@ -1,16 +1,16 @@
var _Contact;
const title = "Neem contact op"; const title = "Neem contact op";
function action() { function action() {
return _action.apply(this, arguments); return _action.apply(this, arguments);
} }
var _ref = /*#__PURE__*/React.createElement(Contact, {
title: title
});
function _action() { function _action() {
_action = babelHelpers.asyncToGenerator(function* () { _action = babelHelpers.asyncToGenerator(function* () {
return _ref; return _Contact || (_Contact = /*#__PURE__*/React.createElement(Contact, {
title: title
}));
}); });
return _action.apply(this, arguments); return _action.apply(this, arguments);
} }

View File

@ -1,5 +1,5 @@
import { declare } from "@babel/helper-plugin-utils"; import { declare } from "@babel/helper-plugin-utils";
import { types as t } from "@babel/core"; import { types as t, template } from "@babel/core";
export default declare((api, options) => { export default declare((api, options) => {
api.assertVersion(7); api.assertVersion(7);
@ -15,9 +15,33 @@ export default declare((api, options) => {
); );
} }
const HOISTED = new WeakSet(); // Element -> Target scope
const HOISTED = new WeakMap();
const immutabilityVisitor = { function declares(node: t.Identifier | t.JSXIdentifier, scope) {
if (
t.isJSXIdentifier(node, { name: "this" }) ||
t.isJSXIdentifier(node, { name: "arguments" }) ||
t.isJSXIdentifier(node, { name: "super" }) ||
t.isJSXIdentifier(node, { name: "new" })
) {
const { path } = scope;
return path.isFunctionParent() && !path.isArrowFunctionExpression();
}
return scope.hasOwnBinding(node.name);
}
function isHoistingScope({ path }) {
return path.isFunctionParent() || path.isLoop() || path.isProgram();
}
function getHoistingScope(scope) {
while (!isHoistingScope(scope)) scope = scope.parent;
return scope;
}
const analyzer = {
enter(path, state) { enter(path, state) {
const stop = () => { const stop = () => {
state.isImmutable = false; state.isImmutable = false;
@ -41,7 +65,8 @@ export default declare((api, options) => {
if ( if (
path.isJSXIdentifier() || path.isJSXIdentifier() ||
path.isIdentifier() || path.isIdentifier() ||
path.isJSXMemberExpression() path.isJSXMemberExpression() ||
path.isJSXNamespacedName()
) { ) {
return; return;
} }
@ -75,6 +100,90 @@ export default declare((api, options) => {
stop(); stop();
} }
}, },
ReferencedIdentifier(path, state) {
const { node } = path;
let { scope } = path;
while (scope) {
// We cannot hoist outside of the previous hoisting target
// scope, so we return early and we don't update it.
if (scope === state.targetScope) return;
// If the scope declares this identifier (or we're at the function
// providing the lexical env binding), we can't hoist the var any
// higher.
if (declares(node, scope)) break;
scope = scope.parent;
}
state.targetScope = getHoistingScope(scope);
},
/*
See the discussion at https://github.com/babel/babel/pull/12967#discussion_r587948958
to uncomment this code.
ReferencedIdentifier(path, state) {
const { node } = path;
let { scope } = path;
let targetScope;
let isNestedScope = true;
let needsHoisting = true;
while (scope) {
// We cannot hoist outside of the previous hoisting target
// scope, so we return early and we don't update it.
if (scope === state.targetScope) return;
// When we hit the scope of our JSX element, we must start
// checking if they declare the binding of the current
// ReferencedIdentifier.
// We don't case about bindings declared in nested scopes,
// because the whole nested scope is hoisted alongside the
// JSX element so it doesn't impose any extra constraint.
if (scope === state.jsxScope) {
isNestedScope = false;
}
// If we are in an upper scope and hoisting to this scope has
// any benefit, we update the possible targetScope to the
// current one.
if (!isNestedScope && needsHoisting) {
targetScope = scope;
}
// When we start walking in upper scopes, avoid hoisting JSX
// elements until we hit a scope introduced by a function or
// loop.
// This is because hoisting from the inside to the outside
// of block or if statements doesn't give any performance
// benefit, and it just unnecessarily increases the code size.
if (scope === state.jsxScope) {
needsHoisting = false;
}
if (!needsHoisting && isHoistingScope(scope)) {
needsHoisting = true;
}
// If the current scope declares the ReferencedIdentifier we
// are checking, we break out of this loop. There are two
// possible scenarios:
// 1. We are in a nested scope, this this declaration means
// that this reference doesn't affect the target scope.
// The targetScope variable is still undefined.
// 2. We are in an upper scope, so this declaration defines
// a new hoisting constraint. The targetScope variable
// refers to the current scope.
if (declares(node, scope)) break;
scope = scope.parent;
}
if (targetScope) state.targetScope = targetScope;
},*/
}; };
return { return {
@ -83,30 +192,70 @@ export default declare((api, options) => {
visitor: { visitor: {
JSXElement(path) { JSXElement(path) {
if (HOISTED.has(path.node)) return; if (HOISTED.has(path.node)) return;
HOISTED.add(path.node); HOISTED.set(path.node, path.scope);
const state = { isImmutable: true }; const name = path.node.openingElement.name;
// This transform takes the option `allowMutablePropsOnTags`, which is an array // This transform takes the option `allowMutablePropsOnTags`, which is an array
// of JSX tags to allow mutable props (such as objects, functions) on. Use sparingly // of JSX tags to allow mutable props (such as objects, functions) on. Use sparingly
// and only on tags you know will never modify their own props. // and only on tags you know will never modify their own props.
let mutablePropsAllowed = false;
if (allowMutablePropsOnTags != null) { if (allowMutablePropsOnTags != null) {
// Get the element's name. If it's a member expression, we use the last part of the path. // Get the element's name. If it's a member expression, we use the last part of the path.
// So the option ["FormattedMessage"] would match "Intl.FormattedMessage". // So the option ["FormattedMessage"] would match "Intl.FormattedMessage".
let namePath = path.get("openingElement.name"); let lastSegment = name;
while (namePath.isJSXMemberExpression()) { while (t.isJSXMemberExpression(lastSegment)) {
namePath = namePath.get("property"); lastSegment = lastSegment.property;
} }
const elementName = namePath.node.name; const elementName = lastSegment.name;
state.mutablePropsAllowed = mutablePropsAllowed = allowMutablePropsOnTags.includes(elementName);
allowMutablePropsOnTags.indexOf(elementName) > -1;
} }
// Traverse all props passed to this element for immutability. const state = {
path.traverse(immutabilityVisitor, state); isImmutable: true,
mutablePropsAllowed,
targetScope: path.scope.getProgramParent(),
};
if (state.isImmutable) path.hoist(); // Traverse all props passed to this element for immutability,
// and compute the target hoisting scope
path.traverse(analyzer, state);
if (!state.isImmutable) return;
const { targetScope } = state;
HOISTED.set(path.node, targetScope);
// In order to avoid hoisting unnecessarily, we need to know which is
// the scope containing the current JSX element. If a parent of the
// current element has already been hoisted, we can consider its target
// scope as the base scope for the current element.
let jsxScope;
let current = path;
while (!jsxScope && current.parentPath.isJSX()) {
current = current.parentPath;
jsxScope = HOISTED.get(current.node);
}
jsxScope ??= getHoistingScope(path.scope);
// Only hoist if it would give us an advantage.
if (targetScope === jsxScope) return;
const id = path.scope.generateUidBasedOnNode(name);
targetScope.push({ id: t.identifier(id) });
let replacement = template.expression.ast`
${t.identifier(id)} || (${t.identifier(id)} = ${path.node})
`;
if (
path.parentPath.isJSXElement() ||
path.parentPath.isJSXAttribute()
) {
replacement = t.jsxExpressionContainer(replacement);
}
path.replaceWith(replacement);
}, },
}, },
}; };

View File

@ -0,0 +1,8 @@
function AComponent () {
const CComponent = () => <div/>
return <BComponent/>
function BComponent () {
return <CComponent/>
}
}

View File

@ -0,0 +1,13 @@
var _div;
function AComponent() {
var _CComponent;
const CComponent = () => _div || (_div = <div />);
return <BComponent />;
function BComponent() {
return _CComponent || (_CComponent = <CComponent />);
}
}

View File

@ -1,17 +1,15 @@
var _ref = <div>child</div>; var _div, _div2;
const AppItem = () => { const AppItem = () => {
return _ref; return _div || (_div = <div>child</div>);
}; };
var _ref2 = <div>
<p>Parent</p>
<AppItem />
</div>;
export default class App extends React.Component { export default class App extends React.Component {
render() { render() {
return _ref2; return _div2 || (_div2 = <div>
<p>Parent</p>
<AppItem />
</div>);
} }
} }

View File

@ -1,20 +1,19 @@
var _ref2 = <div>child</div>; var _p, _div2;
var _ref3 = <p>Parent</p>;
(function () { (function () {
var _div;
class App extends React.Component { class App extends React.Component {
render() { render() {
return _ref; return _div || (_div = <div>
{_p || (_p = <p>Parent</p>)}
<AppItem />
</div>);
} }
} }
const AppItem = () => { const AppItem = () => {
return _ref2; return _div2 || (_div2 = <div>child</div>);
}, };
_ref = <div>
{_ref3}
<AppItem />
</div>;
}); });

View File

@ -1,20 +1,18 @@
var _ref = <div>child</div>; var _div, _p;
var _ref3 = <p>Parent</p>;
(function () { (function () {
const AppItem = () => { var _div2;
return _ref;
};
var _ref2 = <div> const AppItem = () => {
{_ref3} return _div || (_div = <div>child</div>);
<AppItem /> };
</div>;
class App extends React.Component { class App extends React.Component {
render() { render() {
return _ref2; return _div2 || (_div2 = <div>
{_p || (_p = <p>Parent</p>)}
<AppItem />
</div>);
} }
} }

View File

@ -1,16 +1,15 @@
var _div, _div2;
export default class App extends React.Component { export default class App extends React.Component {
render() { render() {
return _ref; return _div || (_div = <div>
<p>Parent</p>
<AppItem />
</div>);
} }
} }
var _ref2 = <div>child</div>;
const AppItem = () => { const AppItem = () => {
return _ref2; return _div2 || (_div2 = <div>child</div>);
}, };
_ref = <div>
<p>Parent</p>
<AppItem />
</div>;

View File

@ -1,9 +1,9 @@
var _ref = <span />; var _span;
var Foo = React.createClass({ var Foo = React.createClass({
render: function () { render: function () {
return <div className={this.props.className}> return <div className={this.props.className}>
{_ref} {_span || (_span = <span />)}
</div>; </div>;
} }
}); });

View File

@ -1,6 +1,6 @@
import React from 'react'; // Regression test for https://github.com/babel/babel/issues/5552 var _div2;
var _ref = <div />; import React from 'react'; // Regression test for https://github.com/babel/babel/issues/5552
class BugReport extends React.Component { class BugReport extends React.Component {
constructor(...args) { constructor(...args) {
@ -8,8 +8,12 @@ class BugReport extends React.Component {
this.thisWontWork = ({ this.thisWontWork = ({
color color
}) => data => { }) => {
return <div color={color}>does not reference data</div>; var _div;
return data => {
return _div || (_div = <div color={color}>does not reference data</div>);
};
}; };
this.thisWorks = ({ this.thisWorks = ({
@ -20,7 +24,7 @@ class BugReport extends React.Component {
} }
render() { render() {
return _ref; return _div2 || (_div2 = <div />);
} }
} }

View File

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

View File

@ -1,7 +1,7 @@
var _Foo;
var Foo = require("Foo"); var Foo = require("Foo");
var _ref = <Foo />;
function render() { function render() {
return _ref; return _Foo || (_Foo = <Foo />);
} }

View File

@ -1,12 +1,10 @@
var _ref = <b></b>; var _b, _span;
var _ref2 = <span></span>;
function render() { function render() {
var children = _ref; var children = _b || (_b = <b></b>);
if (someCondition) { if (someCondition) {
children = _ref2; children = _span || (_span = <span></span>);
} }
return <div>{children}</div>; return <div>{children}</div>;

View File

@ -1,3 +1,5 @@
var _span;
let foo = 'hello'; let foo = 'hello';
const mutate = () => { const mutate = () => {
@ -6,5 +8,5 @@ const mutate = () => {
export const Component = () => { export const Component = () => {
if (Math.random() > 0.5) mutate(); if (Math.random() > 0.5) mutate();
return <span>{foo}</span>; return _span || (_span = <span>{foo}</span>);
}; };

View File

@ -1,5 +1,7 @@
var _span;
let foo = 'hello'; let foo = 'hello';
export const Component = () => { export const Component = () => {
foo = 'goodbye'; foo = 'goodbye';
return <span>{foo}</span>; return _span || (_span = <span>{foo}</span>);
}; };

View File

@ -1,14 +1,13 @@
var _div, _div2;
import React from "react"; import React from "react";
const Parent = ({}) => _ref; const Parent = ({}) => _div || (_div = <div className="parent">
<Child />
</div>);
export default Parent; export default Parent;
var _ref2 = <div className="child"> let Child = () => _div2 || (_div2 = <div className="child">
ChildTextContent ChildTextContent
</div>; </div>);
let Child = () => _ref2,
_ref = <div className="parent">
<Child />
</div>;

View File

@ -1,16 +1,18 @@
function render() { function render() {
var _foo;
const bar = "bar", const bar = "bar",
_ref = <foo bar={bar} />, renderFoo = () => _foo || (_foo = <foo bar={bar} />);
renderFoo = () => _ref;
return renderFoo(); return renderFoo();
} }
function render() { function render() {
var _foo2;
const bar = "bar", const bar = "bar",
renderFoo = () => _ref2, renderFoo = () => _foo2 || (_foo2 = <foo bar={bar} baz={baz} />),
baz = "baz", baz = "baz";
_ref2 = <foo bar={bar} baz={baz} />;
return renderFoo(); return renderFoo();
} }

View File

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

View File

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

View File

@ -1,19 +1,17 @@
var _div, _div2;
import React from "react"; import React from "react";
const HOC = component => component; const HOC = component => component;
const Parent = ({}) => _ref; const Parent = ({}) => _div || (_div = <div className="parent">
<Child />
</div>);
export default Parent; export default Parent;
var _ref2 = <div className="child"> let Child = () => _div2 || (_div2 = <div className="child">
ChildTextContent ChildTextContent
</div>; </div>);
let Child = () => _ref2;
Child = HOC(Child); Child = HOC(Child);
var _ref = <div className="parent">
<Child />
</div>;

View File

@ -1,17 +1,17 @@
function render(text) { function render(text) {
var _ref = <foo>{text}</foo>; var _foo;
return function () { return function () {
return _ref; return _foo || (_foo = <foo>{text}</foo>);
}; };
} }
var Foo2 = require("Foo"); var Foo2 = require("Foo");
function createComponent(text) { function createComponent(text) {
var _ref2 = <Foo2>{text}</Foo2>; var _Foo;
return function render() { return function render() {
return _ref2; return _Foo || (_Foo = <Foo2>{text}</Foo2>);
}; };
} }

View File

@ -1,7 +1,7 @@
var _ref = <div foo={notDeclared}></div>; var _div;
var Foo = React.createClass({ var Foo = React.createClass({
render: function render() { render: function render() {
return _ref; return _div || (_div = <div foo={notDeclared}></div>);
} }
}); });

View File

@ -1,11 +1,9 @@
var _ref = <foo />; var _foo, _div;
function render() { function render() {
return _ref; return _foo || (_foo = <foo />);
} }
var _ref2 = <div className="foo"><input type="checkbox" checked={true} /></div>;
function render() { function render() {
return _ref2; return _div || (_div = <div className="foo"><input type="checkbox" checked={true} /></div>);
} }

View File

@ -0,0 +1,13 @@
import React from "react";
import OtherComponent from "./components/other-component";
export default function App() {
return (
<div>
<LazyComponent />
<OtherComponent />
</div>
);
}
const LazyComponent = React.lazy(() => import("./components/lazy-component"));

View File

@ -0,0 +1,11 @@
var _div;
import React from "react";
import OtherComponent from "./components/other-component";
export default function App() {
return _div || (_div = <div>
<LazyComponent />
<OtherComponent />
</div>);
}
const LazyComponent = React.lazy(() => import("./components/lazy-component"));

View File

@ -1,15 +1,14 @@
var _ref = /*#__PURE__*/babelHelpers.jsx("foo", {}); var _foo;
function render() { function render() {
return _ref; return _foo || (_foo = /*#__PURE__*/babelHelpers.jsx("foo", {}));
} }
function render() { function render() {
var _foo2;
var text = getText(); var text = getText();
var _ref2 = /*#__PURE__*/babelHelpers.jsx("foo", {}, void 0, text);
return function () { return function () {
return _ref2; return _foo2 || (_foo2 = /*#__PURE__*/babelHelpers.jsx("foo", {}, void 0, text));
}; };
} }

View File

@ -1,9 +1,8 @@
function render() { function render() {
var _foo;
var text = getText(); var text = getText();
var _ref = <foo>{text}</foo>;
return function () { return function () {
return _ref; return _foo || (_foo = <foo>{text}</foo>);
}; };
} }

View File

@ -0,0 +1,16 @@
function outer(arg) {
const valueB = null;
const valueA = {};
function inner() {
console.log(
<A keyA={valueA}>
<B keyB={valueB}>
<C keyC={arg} />
</B>
</A>
);
}
inner();
}

View File

@ -0,0 +1,16 @@
function outer(arg) {
var _A;
const valueB = null;
const valueA = {};
function inner() {
console.log(_A || (_A = <A keyA={valueA}>
<B keyB={valueB}>
<C keyC={arg} />
</B>
</A>));
}
inner();
}

View File

@ -0,0 +1,3 @@
function C(x) {
return <div x={x} attr=<span /> />;
}

View File

@ -0,0 +1,5 @@
var _span;
function C(x) {
return <div x={x} attr={_span || (_span = <span />)} />;
}

View File

@ -0,0 +1,3 @@
function C() {
return <div attr=<span /> />;
}

View File

@ -0,0 +1,5 @@
var _div;
function C() {
return _div || (_div = <div attr=<span /> />);
}

View File

@ -0,0 +1,29 @@
function thisExpr() {
return <p>{this.Foo}</p>;
}
function thisJSX() {
return <this.Foo />;
}
class A extends B {
superExpr() {
return <p>{super.Foo}</p>;
}
superJSX() {
return <super.Foo />;
}
}
function argumentsExpr() {
return <p>{arguments.Foo}</p>;
}
function argumentsJSX() {
return <arguments.Foo />;
}
function newTargetExpr() {
return <p>{new.target.Foo}</p>;
}
function newTargetJSX() {
return <new.target.Foo />;
}

View File

@ -0,0 +1,34 @@
function thisExpr() {
return <p>{this.Foo}</p>;
}
function thisJSX() {
return <this.Foo />;
}
class A extends B {
superExpr() {
return <p>{super.Foo}</p>;
}
superJSX() {
return <super.Foo />;
}
}
function argumentsExpr() {
return <p>{arguments.Foo}</p>;
}
function argumentsJSX() {
return <arguments.Foo />;
}
function newTargetExpr() {
return <p>{new.target.Foo}</p>;
}
function newTargetJSX() {
return <new.target.Foo />;
}

View File

@ -1,7 +1,6 @@
function render() { function render() {
var _this$component;
this.component = "div"; this.component = "div";
return () => _this$component || (_this$component = <this.component />);
var _ref = <this.component />;
return () => _ref;
} }

View File

@ -1,14 +1,14 @@
var _ref = <span>Sub Component</span>; var _span;
class Component extends React.Component { class Component extends React.Component {
constructor(...args) { constructor(...args) {
var _this$subComponent;
super(...args); super(...args);
this.subComponent = () => _ref; this.subComponent = () => _span || (_span = <span>Sub Component</span>);
var _ref2 = <this.subComponent />; this.render = () => _this$subComponent || (_this$subComponent = <this.subComponent />);
this.render = () => _ref2;
} }
} }

View File

@ -1,16 +1,14 @@
var _ref = <span>Sub Component</span>; var _span, _els$subComponent;
const els = { const els = {
subComponent: () => _ref subComponent: () => _span || (_span = <span>Sub Component</span>)
}; };
var _ref2 = <els.subComponent />;
class Component extends React.Component { class Component extends React.Component {
constructor(...args) { constructor(...args) {
super(...args); super(...args);
this.render = () => _ref2; this.render = () => _els$subComponent || (_els$subComponent = <els.subComponent />);
} }
} }

View File

@ -0,0 +1,7 @@
function AComponent () {
return <BComponent/>
function BComponent () {
return <n:CComponent />
}
}

View File

@ -0,0 +1,9 @@
var _n$CComponent;
function AComponent() {
return <BComponent />;
function BComponent() {
return _n$CComponent || (_n$CComponent = <n:CComponent />);
}
}

View File

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

View File

@ -1,9 +1,8 @@
function render(_ref) { function render(_ref) {
var _Component;
let text = _ref.text, let text = _ref.text,
className = _ref.className, className = _ref.className,
id = _ref.id; id = _ref.id;
return () => _Component || (_Component = <Component text={text} className={className} id={id} />);
var _ref2 = <Component text={text} className={className} id={id} />;
return () => _ref2;
} }

View File

@ -1,11 +1,10 @@
function render(_ref) { function render(_ref) {
var _Component;
let text = _ref.text, let text = _ref.text,
className = _ref.className, className = _ref.className,
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} />;
// intentionally ignoring props // intentionally ignoring props
return () => _ref2; return () => _Component || (_Component = <Component text={text} className={className} id={id} />);
} }

View File

@ -1,7 +1,6 @@
function render(_ref) { function render(_ref) {
var _Component;
let text = _ref.text; let text = _ref.text;
return () => _Component || (_Component = <Component text={text} />);
var _ref2 = <Component text={text} />;
return () => _ref2;
} }

View File

@ -1,8 +1,8 @@
function render(text) { function render(text) {
var _ref = <div>{text}</div>; var _div;
return function () { return function () {
return _ref; return _div || (_div = <div>{text}</div>);
}; };
} }

View File

@ -1,7 +1,7 @@
function render(offset) { function render(offset) {
var _ref = <div tabIndex={offset + 1} />; var _div;
return function () { return function () {
return _ref; return _div || (_div = <div tabIndex={offset + 1} />);
}; };
} }

View File

@ -1,9 +1,8 @@
var _div;
const OFFSET = 3; const OFFSET = 3;
var _ref = <div tabIndex={OFFSET + 1} />;
var Foo = React.createClass({ var Foo = React.createClass({
render: function () { render: function () {
return _ref; return _div || (_div = <div tabIndex={OFFSET + 1} />);
} }
}); });

View File

@ -1,11 +1,10 @@
var _Intl$FormattedMessag;
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={{
someValue: "A value."
}} />;
var Foo = React.createClass({ var Foo = React.createClass({
render: function () { render: function () {
return _ref; return _Intl$FormattedMessag || (_Intl$FormattedMessag = <Intl.FormattedMessage id="someMessage.foo" defaultMessage={"Some text, " + "and some more too. {someValue}"} description="A test message for babel." values={{
someValue: "A value."
}} />);
} }
}); });

View File

@ -1,9 +1,9 @@
var _ref = <FormattedMessage id="someMessage.foo" defaultMessage={"Some text, " + "and some more too. {someValue}"} description="A test message for babel." values={{ var _FormattedMessage;
someValue: "A value."
}} />;
var Foo = React.createClass({ var Foo = React.createClass({
render: function () { render: function () {
return _ref; return _FormattedMessage || (_FormattedMessage = <FormattedMessage id="someMessage.foo" defaultMessage={"Some text, " + "and some more too. {someValue}"} description="A test message for babel." values={{
someValue: "A value."
}} />);
} }
}); });

View File

@ -1,7 +1,7 @@
var _ref = <div data-text={"Some text, " + "and some more too."} />; var _div;
var Foo = React.createClass({ var Foo = React.createClass({
render: function () { render: function () {
return _ref; return _div || (_div = <div data-text={"Some text, " + "and some more too."} />);
} }
}); });

View File

@ -1,9 +1,8 @@
function render(text) { function render(text) {
var _div;
text += "yes"; text += "yes";
var _ref = <div>{text}</div>;
return function () { return function () {
return _ref; return _div || (_div = <div>{text}</div>);
}; };
} }

View File

@ -1,10 +1,10 @@
var _B;
class A { class A {
render() { render() {
return _ref; return _B || (_B = /*#__PURE__*/React.createElement(B, null));
} }
} }
export default class B {} export default class B {}
var _ref = /*#__PURE__*/React.createElement(B, null);

View File

@ -1,10 +1,10 @@
var _B;
class A { class A {
render() { render() {
return _ref; return _B || (_B = /*#__PURE__*/React.createElement(B, null));
} }
} }
export class B {} export class B {}
var _ref = /*#__PURE__*/React.createElement(B, null);

View File

@ -1,9 +1,9 @@
var _ref = <div className="class-name"> var _div;
Text
</div>;
var Foo = React.createClass({ var Foo = React.createClass({
render: function () { render: function () {
return _ref; return _div || (_div = <div className="class-name">
Text
</div>);
} }
}); });

View File

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

View File

@ -0,0 +1,12 @@
import React from 'react';
const namespace = {
MyComponent: (props) => props.name
};
const buildTest = (name) => {
const { MyComponent } = namespace;
return () => (
<MyComponent name={name} />
);
}

View File

@ -0,0 +1,5 @@
{
"BABEL_8_BREAKING": false,
"plugins": ["transform-react-jsx", "transform-react-constant-elements"],
"presets": ["env"]
}

View File

@ -0,0 +1,20 @@
"use strict";
var _react = babelHelpers.interopRequireDefault(require("react"));
var namespace = {
MyComponent: function MyComponent(props) {
return props.name;
}
};
var buildTest = function buildTest(name) {
var _MyComponent;
var MyComponent = namespace.MyComponent;
return function () {
return _MyComponent || (_MyComponent = /*#__PURE__*/_react["default"].createElement(MyComponent, {
name: name
}));
};
};

View File

@ -0,0 +1,12 @@
import React from 'react';
const namespace = {
MyComponent: (props) => props.name
};
const buildTest = (name) => {
const { MyComponent } = namespace;
return () => (
<MyComponent name={name} />
);
}

View File

@ -0,0 +1,5 @@
{
"BABEL_8_BREAKING": true,
"plugins": ["transform-react-jsx", "transform-react-constant-elements"],
"presets": ["env"]
}

View File

@ -0,0 +1,22 @@
"use strict";
var _react = babelHelpers.interopRequireDefault(require("react"));
var _jsxRuntime = require("react/jsx-runtime");
var namespace = {
MyComponent: function MyComponent(props) {
return props.name;
}
};
var buildTest = function buildTest(name) {
var _MyComponent;
var MyComponent = namespace.MyComponent;
return function () {
return _MyComponent || (_MyComponent = /*#__PURE__*/(0, _jsxRuntime.jsx)(MyComponent, {
name: name
}));
};
};

View File

@ -0,0 +1,6 @@
function Foo({outsetArrows, ...rest}) {
return useMemo(
() => <div outsetArrows={outsetArrows}/>,
[outsetArrows]
);
}

View File

@ -0,0 +1,7 @@
{
"plugins": [
"syntax-jsx",
"transform-react-constant-elements",
"proposal-object-rest-spread"
]
}

View File

@ -0,0 +1,9 @@
function Foo(_ref) {
var _div;
let {
outsetArrows
} = _ref,
rest = babelHelpers.objectWithoutProperties(_ref, ["outsetArrows"]);
return useMemo(() => _div || (_div = <div outsetArrows={outsetArrows} />), [outsetArrows]);
}

View File

@ -0,0 +1,10 @@
import Parent from './Parent';
import Child from './Child';
function MyComponent({closeFn}) {
return (
<Parent render={() => <Child closeFn={closeFn} /> } />
);
}
export default Parent;

View File

@ -0,0 +1,5 @@
{
"BABEL_8_BREAKING": false,
"plugins": ["transform-react-jsx", "transform-react-constant-elements"],
"presets": ["env"]
}

View File

@ -0,0 +1,26 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports["default"] = void 0;
var _Parent = babelHelpers.interopRequireDefault(require("./Parent"));
var _Child2 = babelHelpers.interopRequireDefault(require("./Child"));
function MyComponent(_ref) {
var _Child;
var closeFn = _ref.closeFn;
return /*#__PURE__*/React.createElement(_Parent["default"], {
render: function render() {
return _Child || (_Child = /*#__PURE__*/React.createElement(_Child2["default"], {
closeFn: closeFn
}));
}
});
}
var _default = _Parent["default"];
exports["default"] = _default;

View File

@ -0,0 +1,10 @@
import Parent from './Parent';
import Child from './Child';
function MyComponent({closeFn}) {
return (
<Parent render={() => <Child closeFn={closeFn} /> } />
);
}
export default Parent;

View File

@ -0,0 +1,5 @@
{
"BABEL_8_BREAKING": true,
"plugins": ["transform-react-jsx", "transform-react-constant-elements"],
"presets": ["env"]
}

View File

@ -0,0 +1,28 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports["default"] = void 0;
var _Parent = babelHelpers.interopRequireDefault(require("./Parent"));
var _Child2 = babelHelpers.interopRequireDefault(require("./Child"));
var _jsxRuntime = require("react/jsx-runtime");
function MyComponent(_ref) {
var _Child;
var closeFn = _ref.closeFn;
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_Parent["default"], {
render: function render() {
return _Child || (_Child = /*#__PURE__*/(0, _jsxRuntime.jsx)(_Child2["default"], {
closeFn: closeFn
}));
}
});
}
var _default = _Parent["default"];
exports["default"] = _default;

View File

@ -1,8 +1,4 @@
var _ref = <div className="navbar-header"> var _div;
<a className="navbar-brand" href="/">
<img src="/img/logo/logo-96x36.png" />
</a>
</div>;
let App = /*#__PURE__*/function (_React$Component) { let App = /*#__PURE__*/function (_React$Component) {
babelHelpers.inherits(App, _React$Component); babelHelpers.inherits(App, _React$Component);
@ -17,7 +13,11 @@ let App = /*#__PURE__*/function (_React$Component) {
babelHelpers.createClass(App, [{ babelHelpers.createClass(App, [{
key: "render", key: "render",
value: function render() { value: function render() {
const navbarHeader = _ref; const navbarHeader = _div || (_div = <div className="navbar-header">
<a className="navbar-brand" href="/">
<img src="/img/logo/logo-96x36.png" />
</a>
</div>);
return <div> return <div>
<nav className="navbar navbar-default"> <nav className="navbar navbar-default">
<div className="container"> <div className="container">

View File

@ -1,8 +1,4 @@
var _ref = <div className="navbar-header"> var _div;
<a className="navbar-brand" href="/">
<img src="/img/logo/logo-96x36.png" />
</a>
</div>;
let App = /*#__PURE__*/function (_React$Component) { let App = /*#__PURE__*/function (_React$Component) {
"use strict"; "use strict";
@ -19,7 +15,11 @@ let App = /*#__PURE__*/function (_React$Component) {
babelHelpers.createClass(App, [{ babelHelpers.createClass(App, [{
key: "render", key: "render",
value: function render() { value: function render() {
const navbarHeader = _ref; const navbarHeader = _div || (_div = <div className="navbar-header">
<a className="navbar-brand" href="/">
<img src="/img/logo/logo-96x36.png" />
</a>
</div>);
return <div> return <div>
<nav className="navbar navbar-default"> <nav className="navbar navbar-default">
<div className="container"> <div className="container">