Skip to content
This repository was archived by the owner on Mar 8, 2020. It is now read-only.

Commit a79ef98

Browse files
committedMar 2, 2020
Better heuristic for what is considered expensive work on conditionals
1 parent b6b0c99 commit a79ef98

File tree

3 files changed

+86
-63
lines changed

3 files changed

+86
-63
lines changed
 

‎src/index.js

+24-18
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export default babel => {
2323
return tagName[0].toLowerCase() !== tagName[0] || tagName.includes(".");
2424
}
2525

26-
function isDynamic(expr, path, checkTags) {
26+
function isDynamic(expr, path, { checkMember, checkTags }) {
2727
if (t.isFunction(expr)) return false;
2828
if (
2929
expr.leadingComments &&
@@ -34,7 +34,7 @@ export default babel => {
3434
}
3535
if (
3636
t.isCallExpression(expr) ||
37-
t.isMemberExpression(expr) ||
37+
(checkMember && t.isMemberExpression(expr)) ||
3838
(checkTags && (t.isJSXElement(expr) || t.isJSXFragment(expr)))
3939
)
4040
return true;
@@ -49,8 +49,7 @@ export default babel => {
4949
p.stop();
5050
},
5151
MemberExpression(p) {
52-
dynamic = true;
53-
p.stop();
52+
checkMember && (dynamic = true) && p.stop();
5453
},
5554
JSXElement(p) {
5655
checkTags ? (dynamic = true) && p.stop() : p.skip();
@@ -275,11 +274,12 @@ export default babel => {
275274
let dTest, cond;
276275
if (
277276
t.isConditionalExpression(expr) &&
278-
(isDynamic(expr.consequent, path.get("consequent"), true) ||
279-
isDynamic(expr.alternate, path.get("alternate"), true) ||
280-
(deep && isDynamic(expr.test, path.get("test"))))
277+
(isDynamic(expr.consequent, path.get("consequent"), {
278+
checkTags: true
279+
}) ||
280+
isDynamic(expr.alternate, path.get("alternate"), { checkTags: true }))
281281
) {
282-
dTest = isDynamic(expr.test, path.get("test"));
282+
dTest = isDynamic(expr.test, path.get("test"), { checkMember: true });
283283
if (dTest) {
284284
cond = expr.test;
285285
expr.test = t.callExpression(t.identifier("_c$"), []);
@@ -312,8 +312,10 @@ export default babel => {
312312
nextExpr = nextExpr.left;
313313
nextPath = nextPath.get("left");
314314
}
315-
isDynamic(nextExpr.right, nextPath.get("right"), true) &&
316-
(dTest = isDynamic(nextExpr.left, nextPath.get("left")));
315+
isDynamic(nextExpr.right, nextPath.get("right"), { checkTags: true }) &&
316+
(dTest = isDynamic(nextExpr.left, nextPath.get("left"), {
317+
checkMember: true
318+
}));
317319
if (dTest) {
318320
cond = nextExpr.left;
319321
nextExpr.left = t.callExpression(t.identifier("_c$"), []);
@@ -632,7 +634,7 @@ export default babel => {
632634
isDynamic(
633635
value.expression,
634636
lookupPathForExpr(path, value.expression),
635-
true
637+
{ checkMember: true, checkTags: true }
636638
)
637639
) {
638640
dynamicKeys.push(t.stringLiteral(attribute.name.name));
@@ -728,7 +730,8 @@ export default babel => {
728730
elem,
729731
isDynamic(
730732
attribute.argument,
731-
lookupPathForExpr(path, attribute.argument)
733+
lookupPathForExpr(path, attribute.argument),
734+
{ checkMember: true }
732735
)
733736
? t.arrowFunctionExpression([], attribute.argument)
734737
: attribute.argument,
@@ -825,7 +828,11 @@ export default babel => {
825828
)
826829
);
827830
} else if (
828-
isDynamic(value.expression, lookupPathForExpr(path, value.expression))
831+
isDynamic(
832+
value.expression,
833+
lookupPathForExpr(path, value.expression),
834+
{ checkMember: true }
835+
)
829836
) {
830837
if (key === "textContent") {
831838
const textId = path.scope.generateUidIdentifier("el$");
@@ -1124,11 +1131,10 @@ export default babel => {
11241131
} else if (t.isJSXExpressionContainer(jsx)) {
11251132
if (t.isJSXEmptyExpression(jsx.expression)) return null;
11261133
if (
1127-
!isDynamic(
1128-
jsx.expression,
1129-
lookupPathForExpr(path, jsx.expression),
1130-
!!info.componentChild
1131-
)
1134+
!isDynamic(jsx.expression, lookupPathForExpr(path, jsx.expression), {
1135+
checkMember: true,
1136+
checkTags: !!info.componentChild
1137+
})
11321138
)
11331139
return { exprs: [jsx.expression], template: "" };
11341140
const expr =

‎test/__dom_fixtures__/conditionalExpressions/code.js

+16-10
Original file line numberDiff line numberDiff line change
@@ -4,28 +4,34 @@ const template2 = <div>{state.dynamic}</div>;
44

55
const template3 = <div>{simple ? good : bad}</div>;
66

7-
const template4 = <div>{state.dynamic ? good() : bad}</div>;
7+
const template4 = <div>{simple ? good() : bad}</div>
88

9-
const template5 = <div>{state.dynamic && good()}</div>;
9+
const template5 = <div>{state.dynamic ? good() : bad}</div>;
1010

11-
const template6 = (
11+
const template6 = <div>{state.dynamic && good()}</div>;
12+
13+
const template7 = (
1214
<div>{state.count > 5 ? (state.dynamic ? best : good()) : bad}</div>
1315
);
1416

15-
const template7 = <div>{state.dynamic && state.something && good()}</div>;
17+
const template8 = <div>{state.dynamic && state.something && good()}</div>;
1618

17-
const template8 = <div>{(state.dynamic && good()) || bad}</div>;
19+
const template9 = <div>{(state.dynamic && good()) || bad}</div>;
1820

19-
const template9 = (
21+
const template10 = (
2022
<div>{state.a ? "a" : state.b ? "b" : state.c ? "c" : "fallback"}</div>
2123
);
2224

23-
const template10 = <Comp render={state.dynamic ? good() : bad} />;
25+
const template11 = (
26+
<div>{state.a ? a() : state.b ? b() : state.c ? "c" : "fallback"}</div>
27+
);
28+
29+
const template12 = <Comp render={state.dynamic ? good() : bad} />;
2430

2531
// no dynamic predicate
26-
const template11 = <Comp render={state.dynamic ? good : bad} />;
32+
const template13 = <Comp render={state.dynamic ? good : bad} />;
2733

28-
const template12 = <Comp render={state.dynamic && good()} />;
34+
const template14 = <Comp render={state.dynamic && good()} />;
2935

3036
// no dynamic predicate
31-
const template13 = <Comp render={state.dynamic && good} />;
37+
const template15 = <Comp render={state.dynamic && good} />;

‎test/__dom_fixtures__/conditionalExpressions/output.js

+46-35
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,7 @@ const template3 = (function() {
3434
const template4 = (function() {
3535
const _el$4 = _tmpl$.cloneNode(true);
3636

37-
_$insert(
38-
_el$4,
39-
(() => {
40-
const _c$ = _$wrapCondition(() => state.dynamic);
41-
42-
return () => (_c$() ? good() : bad);
43-
})()
44-
);
37+
_$insert(_el$4, () => (simple ? good() : bad));
4538

4639
return _el$4;
4740
})();
@@ -54,7 +47,7 @@ const template5 = (function() {
5447
(() => {
5548
const _c$ = _$wrapCondition(() => state.dynamic);
5649

57-
return () => _c$() && good();
50+
return () => (_c$() ? good() : bad);
5851
})()
5952
);
6053

@@ -66,6 +59,21 @@ const template6 = (function() {
6659

6760
_$insert(
6861
_el$6,
62+
(() => {
63+
const _c$ = _$wrapCondition(() => state.dynamic);
64+
65+
return () => _c$() && good();
66+
})()
67+
);
68+
69+
return _el$6;
70+
})();
71+
72+
const template7 = (function() {
73+
const _el$7 = _tmpl$.cloneNode(true);
74+
75+
_$insert(
76+
_el$7,
6977
(() => {
7078
const _c$ = _$wrapCondition(() => state.count > 5);
7179

@@ -80,69 +88,72 @@ const template6 = (function() {
8088
})()
8189
);
8290

83-
return _el$6;
91+
return _el$7;
8492
})();
8593

86-
const template7 = (function() {
87-
const _el$7 = _tmpl$.cloneNode(true);
94+
const template8 = (function() {
95+
const _el$8 = _tmpl$.cloneNode(true);
8896

8997
_$insert(
90-
_el$7,
98+
_el$8,
9199
(() => {
92100
const _c$ = _$wrapCondition(() => state.dynamic && state.something);
93101

94102
return () => _c$() && good();
95103
})()
96104
);
97105

98-
return _el$7;
106+
return _el$8;
99107
})();
100108

101-
const template8 = (function() {
102-
const _el$8 = _tmpl$.cloneNode(true);
109+
const template9 = (function() {
110+
const _el$9 = _tmpl$.cloneNode(true);
103111

104112
_$insert(
105-
_el$8,
113+
_el$9,
106114
(() => {
107115
const _c$ = _$wrapCondition(() => state.dynamic);
108116

109117
return () => (_c$() && good()) || bad;
110118
})()
111119
);
112120

113-
return _el$8;
121+
return _el$9;
114122
})();
115123

116-
const template9 = (function() {
117-
const _el$9 = _tmpl$.cloneNode(true);
124+
const template10 = (function() {
125+
const _el$10 = _tmpl$.cloneNode(true);
126+
127+
_$insert(_el$10, () =>
128+
state.a ? "a" : state.b ? "b" : state.c ? "c" : "fallback"
129+
);
130+
131+
return _el$10;
132+
})();
133+
134+
const template11 = (function() {
135+
const _el$11 = _tmpl$.cloneNode(true);
118136

119137
_$insert(
120-
_el$9,
138+
_el$11,
121139
(() => {
122140
const _c$ = _$wrapCondition(() => state.a);
123141

124142
return () =>
125143
_c$()
126-
? "a"
144+
? a()
127145
: (() => {
128146
const _c$ = _$wrapCondition(() => state.b);
129147

130-
return () =>
131-
_c$()
132-
? "b"
133-
: (() => {
134-
const _c$ = _$wrapCondition(() => state.c);
135-
136-
return () => (_c$() ? "c" : "fallback");
137-
})();
148+
return () => (_c$() ? b() : state.c ? "c" : "fallback");
138149
})();
139150
})()
140151
);
141152

142-
return _el$9;
153+
return _el$11;
143154
})();
144155

145-
const template10 = _$createComponent(
156+
const template12 = _$createComponent(
146157
Comp,
147158
{
148159
render: (() => {
@@ -154,15 +165,15 @@ const template10 = _$createComponent(
154165
_ck$
155166
); // no dynamic predicate
156167

157-
const template11 = _$createComponent(
168+
const template13 = _$createComponent(
158169
Comp,
159170
{
160171
render: () => (state.dynamic ? good : bad)
161172
},
162173
_ck$
163174
);
164175

165-
const template12 = _$createComponent(
176+
const template14 = _$createComponent(
166177
Comp,
167178
{
168179
render: (() => {
@@ -174,7 +185,7 @@ const template12 = _$createComponent(
174185
_ck$
175186
); // no dynamic predicate
176187

177-
const template13 = _$createComponent(
188+
const template15 = _$createComponent(
178189
Comp,
179190
{
180191
render: () => state.dynamic && good

0 commit comments

Comments
 (0)
This repository has been archived.