Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lazily initialize and cache constant JSX elements #12967

Merged
merged 12 commits into from Mar 6, 2021
Expand Up @@ -18,6 +18,19 @@ export default declare((api, options) => {
// Element -> Target scope
const HOISTED = new WeakMap();

function declares(
node: t.ThisExpression | t.Identifier | t.JSXIdentifier,
scope,
) {
// Ideally this should always be a ThisExpression 🤷
if (t.isThisExpression(node) || t.isJSXIdentifier(node, { name: "this" })) {
nicolo-ribaudo marked this conversation as resolved.
Show resolved Hide resolved
const { path } = scope;
return path.isFunctionParent() && !path.isArrowFunctionExpression();
}

return scope.hasOwnBinding(node.name);
}

const analyzer = {
enter(path, state) {
const stop = () => {
Expand Down Expand Up @@ -76,9 +89,9 @@ export default declare((api, options) => {
stop();
}
},
ReferencedIdentifier(path, state) {
const { name } = path.node;
let scope = path.scope;
"ReferencedIdentifier|ThisExpression"(path, state) {
const { node } = path;
let { scope } = path;
let targetScope;

let isNestedScope = true;
Expand Down Expand Up @@ -131,7 +144,7 @@ export default declare((api, options) => {
// 2. We are in an upper scope, so this declaration defines
// a new hoisting constraint. The targetScope variable
// refers to the current scope.
if (scope.hasOwnBinding(name)) break;
if (declares(node, scope)) break;

scope = scope.parent;
}
Expand Down
@@ -1,6 +1,6 @@
var _this$component;

function render() {
var _this$component;

this.component = "div";
return () => _this$component || (_this$component = <this.component />);
nicolo-ribaudo marked this conversation as resolved.
Show resolved Hide resolved
}
@@ -1,7 +1,9 @@
var _span, _this$subComponent;
var _span;

class Component extends React.Component {
constructor(...args) {
var _this$subComponent;

super(...args);

this.subComponent = () => _span || (_span = <span>Sub Component</span>);
Expand Down