Skip to content

Commit

Permalink
Compress output for optional chain with multiple ?.
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolo-ribaudo committed Jul 3, 2023
1 parent b849fc1 commit ecb8440
Show file tree
Hide file tree
Showing 24 changed files with 107 additions and 113 deletions.
68 changes: 31 additions & 37 deletions packages/babel-plugin-transform-optional-chaining/src/transform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ import {
} from "@babel/helper-skip-transparent-expression-wrappers";
import { willPathCastToBoolean, findOutermostTransparentParent } from "./util";

const { ast } = template.expression;

function isSimpleMemberExpression(
expression: t.Expression | t.Super,
): expression is t.Identifier | t.Super | t.MemberExpression {
Expand Down Expand Up @@ -50,6 +48,15 @@ function needsMemoize(
}
}

const NULLISH_CHECK = template.expression(
`%%check%% === null || %%ref%% === void 0`,
);
const NULLISH_CHECK_NO_DDA = template.expression(`%%check%% == null`);
const NULLISH_CHECK_NEG = template.expression(
`%%check%% !== null && %%ref%% !== void 0`,
);
const NULLISH_CHECK_NO_DDA_NEG = template.expression(`%%check%% != null`);

interface OptionalChainAssumptions {
pureGetters: boolean;
noDocumentAll: boolean;
Expand Down Expand Up @@ -98,6 +105,8 @@ export function transformOptionalChain(
}
}

const checks = [];

for (let i = optionals.length - 1; i >= 0; i--) {
const node = optionals[i] as unknown as
| t.MemberExpression
Expand Down Expand Up @@ -171,43 +180,28 @@ export function transformOptionalChain(
}
}

const replacement = replacementPath.node;
const data = { check: t.cloneNode(check), ref: t.cloneNode(ref) };
// We make `ref` non-enumerable, so that @babel/template doesn't throw
// in the noDocumentAll template if it's not used.
Object.defineProperty(data, "ref", { enumerable: false });
checks.push(data);
}

if (willReplacementCastToBoolean) {
const nonNullishCheck = noDocumentAll
? ast`${t.cloneNode(check)} != null`
: ast`
${t.cloneNode(check)} !== null && ${t.cloneNode(ref)} !== void 0`;
let result = replacementPath.node;
if (wrapLast) result = wrapLast(result);

// `if (a?.b) {}` transformed to `if (a != null && a.b) {}`
// we don't need to return `void 0` because the returned value will
// eventually cast to boolean.
replacementPath.replaceWith(
t.logicalExpression(
"&&",
nonNullishCheck,
i === 0 && wrapLast ? wrapLast(replacement) : replacement,
),
);
replacementPath = skipTransparentExprWrappers(
replacementPath.get("right"),
);
} else {
const nullishCheck = noDocumentAll
? ast`${t.cloneNode(check)} == null`
: ast`
${t.cloneNode(check)} === null || ${t.cloneNode(ref)} === void 0`;
replacementPath.replaceWith(
t.conditionalExpression(
nullishCheck,
ifNullish(),
i === 0 && wrapLast ? wrapLast(replacement) : replacement,
),
);
replacementPath = skipTransparentExprWrappers(
replacementPath.get("alternate"),
);
}
if (willReplacementCastToBoolean) {
const check = checks
.map(noDocumentAll ? NULLISH_CHECK_NO_DDA_NEG : NULLISH_CHECK_NEG)
.reduce((expr, check) => t.logicalExpression("&&", expr, check));
replacementPath.replaceWith(template.expression.ast`${check} && ${result}`);
} else {
const check = checks
.map(noDocumentAll ? NULLISH_CHECK_NO_DDA : NULLISH_CHECK)
.reduce((expr, check) => t.logicalExpression("||", expr, check));
replacementPath.replaceWith(
template.expression.ast`${check} ? ${ifNullish()} : ${result}`,
);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const obj = {
}
};
const a = obj == null ? void 0 : obj.a;
const b = obj == null ? void 0 : (_obj$a = obj.a) == null ? void 0 : _obj$a.b;
const bad = obj == null ? void 0 : (_obj$b = obj.b) == null ? void 0 : _obj$b.b;
const b = obj == null || (_obj$a = obj.a) == null ? void 0 : _obj$a.b;
const bad = obj == null || (_obj$b = obj.b) == null ? void 0 : _obj$b.b;
let val;
val = obj == null ? void 0 : (_obj$a2 = obj.a) == null ? void 0 : _obj$a2.b;
val = obj == null || (_obj$a2 = obj.a) == null ? void 0 : _obj$a2.b;
Original file line number Diff line number Diff line change
Expand Up @@ -70,15 +70,15 @@ class C {
}
static testLogicalInReturn(o) {
var _o$a$b5, _o$a2;
return (o == null ? void 0 : (_o$a$b5 = o.a.b) == null ? void 0 : _o$a$b5.c.d) && (o == null ? void 0 : (_o$a2 = o.a) == null ? void 0 : _o$a2.b.c.d);
return (o == null || (_o$a$b5 = o.a.b) == null ? void 0 : _o$a$b5.c.d) && (o == null || (_o$a2 = o.a) == null ? void 0 : _o$a2.b.c.d);
}
static testNullishCoalescing(o) {
var _o$a$b$c$non_existent, _o$a$b6, _o$a$b7, _o$a$b$c$non_existent3, _o$a$b10;
if ((_o$a$b$c$non_existent = o == null ? void 0 : (_o$a$b6 = o.a.b) == null ? void 0 : _o$a$b6.c.non_existent) != null ? _o$a$b$c$non_existent : o == null ? void 0 : (_o$a$b7 = o.a.b) == null ? void 0 : _o$a$b7.c.d) {
if ((_o$a$b$c$non_existent = o == null || (_o$a$b6 = o.a.b) == null ? void 0 : _o$a$b6.c.non_existent) != null ? _o$a$b$c$non_existent : o == null || (_o$a$b7 = o.a.b) == null ? void 0 : _o$a$b7.c.d) {
var _o$a$b$c$non_existent2, _o$a$b8, _o$a$b9;
return (_o$a$b$c$non_existent2 = o == null ? void 0 : (_o$a$b8 = o.a.b) == null ? void 0 : _o$a$b8.c.non_existent) != null ? _o$a$b$c$non_existent2 : o == null ? void 0 : (_o$a$b9 = o.a.b) == null ? void 0 : _o$a$b9.c.d;
return (_o$a$b$c$non_existent2 = o == null || (_o$a$b8 = o.a.b) == null ? void 0 : _o$a$b8.c.non_existent) != null ? _o$a$b$c$non_existent2 : o == null || (_o$a$b9 = o.a.b) == null ? void 0 : _o$a$b9.c.d;
}
return (_o$a$b$c$non_existent3 = o == null ? void 0 : (_o$a$b10 = o.a.b) == null ? void 0 : _o$a$b10.c.non_existent) != null ? _o$a$b$c$non_existent3 : o;
return (_o$a$b$c$non_existent3 = o == null || (_o$a$b10 = o.a.b) == null ? void 0 : _o$a$b10.c.non_existent) != null ? _o$a$b$c$non_existent3 : o;
}
}
C.test();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,18 @@ function g({
function h(a, {
b = (() => {
var _a$b, _a$b$c;
return (_a$b = a.b) == null ? void 0 : (_a$b$c = _a$b.c) == null ? void 0 : _a$b$c.d.e;
return (_a$b = a.b) == null || (_a$b$c = _a$b.c) == null ? void 0 : _a$b$c.d.e;
})()
}) {}
function i(a, {
b = (() => {
var _a$b2, _a$b2$c;
return (_a$b2 = a.b) == null ? void 0 : (_a$b2$c = _a$b2.c) == null ? void 0 : _a$b2$c.d;
return (_a$b2 = a.b) == null || (_a$b2$c = _a$b2.c) == null ? void 0 : _a$b2$c.d;
})().e
}) {}
function j(a, {
b = (() => {
var _a$b3;
return a == null ? void 0 : (_a$b3 = a.b) == null ? void 0 : _a$b3.c().d.e;
return a == null || (_a$b3 = a.b) == null ? void 0 : _a$b3.c().d.e;
})()
}) {}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
function test(foo) {
var _foo$bar, _foo$get, _foo$bar2, _foo$bar3, _foo$bar$baz, _foo$bar4, _foo$bar$baz2, _foo$bar5, _foo$bar6, _foo$bar7, _foo$bar8, _foo$bar9, _foo$bar10, _foo$bar10$baz, _foo$bar11, _foo$bar11$baz;
foo == null ? void 0 : foo.bar;
foo == null ? void 0 : (_foo$bar = foo.bar) == null ? void 0 : _foo$bar.baz;
foo == null || (_foo$bar = foo.bar) == null ? void 0 : _foo$bar.baz;
foo == null ? void 0 : foo(foo);
foo == null ? void 0 : foo.bar();
(_foo$get = foo.get(bar)) == null ? void 0 : _foo$get();
Expand All @@ -10,9 +10,9 @@ function test(foo) {
(_foo$bar$baz = (_foo$bar4 = foo.bar()).baz) == null ? void 0 : _foo$bar$baz.call(_foo$bar4);
(_foo$bar$baz2 = (_foo$bar5 = foo[bar]()).baz) == null ? void 0 : _foo$bar$baz2.call(_foo$bar5);
(_foo$bar6 = foo.bar) == null ? void 0 : _foo$bar6.call(foo, foo.bar, false);
foo == null ? void 0 : (_foo$bar7 = foo.bar) == null ? void 0 : _foo$bar7.call(foo, foo.bar, true);
foo == null || (_foo$bar7 = foo.bar) == null ? void 0 : _foo$bar7.call(foo, foo.bar, true);
(_foo$bar8 = foo.bar) == null ? void 0 : _foo$bar8.baz(foo.bar, false);
foo == null ? void 0 : (_foo$bar9 = foo.bar) == null ? void 0 : _foo$bar9.baz(foo.bar, true);
(_foo$bar10 = foo.bar) == null ? void 0 : (_foo$bar10$baz = _foo$bar10.baz) == null ? void 0 : _foo$bar10$baz.call(_foo$bar10, foo.bar, false);
foo == null ? void 0 : (_foo$bar11 = foo.bar) == null ? void 0 : (_foo$bar11$baz = _foo$bar11.baz) == null ? void 0 : _foo$bar11$baz.call(_foo$bar11, foo.bar, true);
foo == null || (_foo$bar9 = foo.bar) == null ? void 0 : _foo$bar9.baz(foo.bar, true);
(_foo$bar10 = foo.bar) == null || (_foo$bar10$baz = _foo$bar10.baz) == null ? void 0 : _foo$bar10$baz.call(_foo$bar10, foo.bar, false);
foo == null || (_foo$bar11 = foo.bar) == null || (_foo$bar11$baz = _foo$bar11.baz) == null ? void 0 : _foo$bar11$baz.call(_foo$bar11, foo.bar, true);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ var _foo, _foo2, _foo3, _foo$bar, _foo4, _foo5, _foo5$bar;
foo === null || foo === void 0 ? void 0 : foo(foo);
(_foo = foo) === null || _foo === void 0 ? void 0 : _foo.bar();
foo.bar === null || foo.bar === void 0 ? void 0 : foo.bar(foo.bar, false);
(_foo2 = foo) === null || _foo2 === void 0 ? void 0 : _foo2.bar === null || _foo2.bar === void 0 ? void 0 : _foo2.bar(foo.bar, true);
(_foo2 = foo) === null || _foo2 === void 0 || _foo2.bar === null || _foo2.bar === void 0 ? void 0 : _foo2.bar(foo.bar, true);
foo === null || foo === void 0 ? void 0 : foo().bar;
foo === null || foo === void 0 ? void 0 : (_foo3 = foo()) === null || _foo3 === void 0 ? void 0 : _foo3.bar;
foo === null || foo === void 0 || (_foo3 = foo()) === null || _foo3 === void 0 ? void 0 : _foo3.bar;
foo.bar === null || foo.bar === void 0 ? void 0 : foo.bar().baz;
foo.bar === null || foo.bar === void 0 ? void 0 : (_foo$bar = foo.bar()) === null || _foo$bar === void 0 ? void 0 : _foo$bar.baz;
(_foo4 = foo) === null || _foo4 === void 0 ? void 0 : _foo4.bar === null || _foo4.bar === void 0 ? void 0 : _foo4.bar().baz;
(_foo5 = foo) === null || _foo5 === void 0 ? void 0 : _foo5.bar === null || _foo5.bar === void 0 ? void 0 : (_foo5$bar = _foo5.bar()) === null || _foo5$bar === void 0 ? void 0 : _foo5$bar.baz;
foo.bar === null || foo.bar === void 0 || (_foo$bar = foo.bar()) === null || _foo$bar === void 0 ? void 0 : _foo$bar.baz;
(_foo4 = foo) === null || _foo4 === void 0 || _foo4.bar === null || _foo4.bar === void 0 ? void 0 : _foo4.bar().baz;
(_foo5 = foo) === null || _foo5 === void 0 || _foo5.bar === null || _foo5.bar === void 0 || (_foo5$bar = _foo5.bar()) === null || _foo5$bar === void 0 ? void 0 : _foo5$bar.baz;
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
function test(foo) {
var _foo$bar, _foo$get, _foo$bar2, _foo$bar3, _foo$bar$baz, _foo$bar4, _foo$bar$baz2, _foo$bar5, _foo$bar6, _foo$bar7, _foo$bar8, _foo$bar9;
foo === null || foo === void 0 ? void 0 : foo.bar;
foo === null || foo === void 0 ? void 0 : (_foo$bar = foo.bar) === null || _foo$bar === void 0 ? void 0 : _foo$bar.baz;
foo === null || foo === void 0 || (_foo$bar = foo.bar) === null || _foo$bar === void 0 ? void 0 : _foo$bar.baz;
foo === null || foo === void 0 ? void 0 : foo(foo);
foo === null || foo === void 0 ? void 0 : foo.bar();
(_foo$get = foo.get(bar)) === null || _foo$get === void 0 ? void 0 : _foo$get();
Expand All @@ -10,9 +10,9 @@ function test(foo) {
(_foo$bar$baz = (_foo$bar4 = foo.bar()).baz) === null || _foo$bar$baz === void 0 ? void 0 : _foo$bar$baz.call(_foo$bar4);
(_foo$bar$baz2 = (_foo$bar5 = foo[bar]()).baz) === null || _foo$bar$baz2 === void 0 ? void 0 : _foo$bar$baz2.call(_foo$bar5);
foo.bar === null || foo.bar === void 0 ? void 0 : foo.bar(foo.bar, false);
foo === null || foo === void 0 ? void 0 : foo.bar === null || foo.bar === void 0 ? void 0 : foo.bar(foo.bar, true);
foo === null || foo === void 0 || foo.bar === null || foo.bar === void 0 ? void 0 : foo.bar(foo.bar, true);
(_foo$bar6 = foo.bar) === null || _foo$bar6 === void 0 ? void 0 : _foo$bar6.baz(foo.bar, false);
foo === null || foo === void 0 ? void 0 : (_foo$bar7 = foo.bar) === null || _foo$bar7 === void 0 ? void 0 : _foo$bar7.baz(foo.bar, true);
(_foo$bar8 = foo.bar) === null || _foo$bar8 === void 0 ? void 0 : _foo$bar8.baz === null || _foo$bar8.baz === void 0 ? void 0 : _foo$bar8.baz(foo.bar, false);
foo === null || foo === void 0 ? void 0 : (_foo$bar9 = foo.bar) === null || _foo$bar9 === void 0 ? void 0 : _foo$bar9.baz === null || _foo$bar9.baz === void 0 ? void 0 : _foo$bar9.baz(foo.bar, true);
foo === null || foo === void 0 || (_foo$bar7 = foo.bar) === null || _foo$bar7 === void 0 ? void 0 : _foo$bar7.baz(foo.bar, true);
(_foo$bar8 = foo.bar) === null || _foo$bar8 === void 0 || _foo$bar8.baz === null || _foo$bar8.baz === void 0 ? void 0 : _foo$bar8.baz(foo.bar, false);
foo === null || foo === void 0 || (_foo$bar9 = foo.bar) === null || _foo$bar9 === void 0 || _foo$bar9.baz === null || _foo$bar9.baz === void 0 ? void 0 : _foo$bar9.baz(foo.bar, true);
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const obj = {
}
};
const a = obj === null || obj === void 0 ? void 0 : obj.a;
const b = obj === null || obj === void 0 ? void 0 : (_obj$a = obj.a) === null || _obj$a === void 0 ? void 0 : _obj$a.b;
const bad = obj === null || obj === void 0 ? void 0 : (_obj$b = obj.b) === null || _obj$b === void 0 ? void 0 : _obj$b.b;
const b = obj === null || obj === void 0 || (_obj$a = obj.a) === null || _obj$a === void 0 ? void 0 : _obj$a.b;
const bad = obj === null || obj === void 0 || (_obj$b = obj.b) === null || _obj$b === void 0 ? void 0 : _obj$b.b;
let val;
val = obj === null || obj === void 0 ? void 0 : (_obj$a2 = obj.a) === null || _obj$a2 === void 0 ? void 0 : _obj$a2.b;
val = obj === null || obj === void 0 || (_obj$a2 = obj.a) === null || _obj$a2 === void 0 ? void 0 : _obj$a2.b;
Original file line number Diff line number Diff line change
Expand Up @@ -70,15 +70,15 @@ class C {
}
static testLogicalInReturn(o) {
var _o$a$b5, _o$a2;
return (o === null || o === void 0 ? void 0 : (_o$a$b5 = o.a.b) === null || _o$a$b5 === void 0 ? void 0 : _o$a$b5.c.d) && (o === null || o === void 0 ? void 0 : (_o$a2 = o.a) === null || _o$a2 === void 0 ? void 0 : _o$a2.b.c.d);
return (o === null || o === void 0 || (_o$a$b5 = o.a.b) === null || _o$a$b5 === void 0 ? void 0 : _o$a$b5.c.d) && (o === null || o === void 0 || (_o$a2 = o.a) === null || _o$a2 === void 0 ? void 0 : _o$a2.b.c.d);
}
static testNullishCoalescing(o) {
var _o$a$b$c$non_existent, _o$a$b6, _o$a$b7, _o$a$b$c$non_existent3, _o$a$b10;
if ((_o$a$b$c$non_existent = o === null || o === void 0 ? void 0 : (_o$a$b6 = o.a.b) === null || _o$a$b6 === void 0 ? void 0 : _o$a$b6.c.non_existent) !== null && _o$a$b$c$non_existent !== void 0 ? _o$a$b$c$non_existent : o === null || o === void 0 ? void 0 : (_o$a$b7 = o.a.b) === null || _o$a$b7 === void 0 ? void 0 : _o$a$b7.c.d) {
if ((_o$a$b$c$non_existent = o === null || o === void 0 || (_o$a$b6 = o.a.b) === null || _o$a$b6 === void 0 ? void 0 : _o$a$b6.c.non_existent) !== null && _o$a$b$c$non_existent !== void 0 ? _o$a$b$c$non_existent : o === null || o === void 0 || (_o$a$b7 = o.a.b) === null || _o$a$b7 === void 0 ? void 0 : _o$a$b7.c.d) {
var _o$a$b$c$non_existent2, _o$a$b8, _o$a$b9;
return (_o$a$b$c$non_existent2 = o === null || o === void 0 ? void 0 : (_o$a$b8 = o.a.b) === null || _o$a$b8 === void 0 ? void 0 : _o$a$b8.c.non_existent) !== null && _o$a$b$c$non_existent2 !== void 0 ? _o$a$b$c$non_existent2 : o === null || o === void 0 ? void 0 : (_o$a$b9 = o.a.b) === null || _o$a$b9 === void 0 ? void 0 : _o$a$b9.c.d;
return (_o$a$b$c$non_existent2 = o === null || o === void 0 || (_o$a$b8 = o.a.b) === null || _o$a$b8 === void 0 ? void 0 : _o$a$b8.c.non_existent) !== null && _o$a$b$c$non_existent2 !== void 0 ? _o$a$b$c$non_existent2 : o === null || o === void 0 || (_o$a$b9 = o.a.b) === null || _o$a$b9 === void 0 ? void 0 : _o$a$b9.c.d;
}
return (_o$a$b$c$non_existent3 = o === null || o === void 0 ? void 0 : (_o$a$b10 = o.a.b) === null || _o$a$b10 === void 0 ? void 0 : _o$a$b10.c.non_existent) !== null && _o$a$b$c$non_existent3 !== void 0 ? _o$a$b$c$non_existent3 : o;
return (_o$a$b$c$non_existent3 = o === null || o === void 0 || (_o$a$b10 = o.a.b) === null || _o$a$b10 === void 0 ? void 0 : _o$a$b10.c.non_existent) !== null && _o$a$b$c$non_existent3 !== void 0 ? _o$a$b$c$non_existent3 : o;
}
}
C.test();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const obj = {
b: 0
}
};
let test = obj === null || obj === void 0 ? true : (_obj$a = obj.a) === null || _obj$a === void 0 ? true : delete _obj$a.b;
let test = obj === null || obj === void 0 || (_obj$a = obj.a) === null || _obj$a === void 0 ? true : delete _obj$a.b;
test = obj === null || obj === void 0 ? true : delete obj.a.b;
test = obj === null || obj === void 0 ? true : (_obj$b = obj.b) === null || _obj$b === void 0 ? true : delete _obj$b.b;
test = obj === null || obj === void 0 || (_obj$b = obj.b) === null || _obj$b === void 0 ? true : delete _obj$b.b;
obj === null || obj === void 0 ? true : delete obj.a;
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ var _foo, _foo2;
foo == null ? void 0 : foo(foo);
(_foo = foo) == null ? void 0 : _foo.bar();
foo.bar == null ? void 0 : foo.bar(foo.bar, false);
(_foo2 = foo) == null ? void 0 : _foo2.bar == null ? void 0 : _foo2.bar(foo.bar, true);
(_foo2 = foo) == null || _foo2.bar == null ? void 0 : _foo2.bar(foo.bar, true);

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,18 @@ function g({
function h(a, {
b = (() => {
var _a$b, _a$b$c;
return (_a$b = a.b) == null ? void 0 : (_a$b$c = _a$b.c) == null ? void 0 : _a$b$c.d.e;
return (_a$b = a.b) == null || (_a$b$c = _a$b.c) == null ? void 0 : _a$b$c.d.e;
})()
}) {}
function i(a, {
b = (() => {
var _a$b2, _a$b2$c;
return (_a$b2 = a.b) == null ? void 0 : (_a$b2$c = _a$b2.c) == null ? void 0 : _a$b2$c.d;
return (_a$b2 = a.b) == null || (_a$b2$c = _a$b2.c) == null ? void 0 : _a$b2$c.d;
})().e
}) {}
function j(a, {
b = (() => {
var _a$b3;
return a == null ? void 0 : (_a$b3 = a.b) == null ? void 0 : _a$b3.c().d.e;
return a == null || (_a$b3 = a.b) == null ? void 0 : _a$b3.c().d.e;
})()
}) {}
Loading

0 comments on commit ecb8440

Please sign in to comment.