-
-
Notifications
You must be signed in to change notification settings - Fork 5.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
optimize optional chain when expression will be cast to boolean (#12291)
- Loading branch information
Showing
33 changed files
with
1,611 additions
and
99 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
45 changes: 45 additions & 0 deletions
45
packages/babel-helper-member-expression-to-functions/src/util.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
/** | ||
* Test if a NodePath will be cast to boolean when evaluated. | ||
* | ||
* @example | ||
* // returns true | ||
* const nodePathAQDotB = NodePath("if (a?.#b) {}").get("test"); // a?.#b | ||
* willPathCastToBoolean(nodePathAQDotB) | ||
* @example | ||
* // returns false | ||
* willPathCastToBoolean(NodePath("a?.#b")) | ||
* @todo Respect transparent expression wrappers | ||
* @see {@link packages/babel-plugin-proposal-optional-chaining/src/util.js} | ||
* @param {NodePath} path | ||
* @returns {boolean} | ||
*/ | ||
export function willPathCastToBoolean(path: NodePath): boolean { | ||
const maybeWrapped = path; | ||
const { node, parentPath } = maybeWrapped; | ||
if (parentPath.isLogicalExpression()) { | ||
const { operator, right } = parentPath.node; | ||
if ( | ||
operator === "&&" || | ||
operator === "||" || | ||
(operator === "??" && node === right) | ||
) { | ||
return willPathCastToBoolean(parentPath); | ||
} | ||
} | ||
if (parentPath.isSequenceExpression()) { | ||
const { expressions } = parentPath.node; | ||
if (expressions[expressions.length - 1] === node) { | ||
return willPathCastToBoolean(parentPath); | ||
} else { | ||
// if it is in the middle of a sequence expression, we don't | ||
// care the return value so just cast to boolean for smaller | ||
// output | ||
return true; | ||
} | ||
} | ||
return ( | ||
parentPath.isConditional({ test: node }) || | ||
parentPath.isUnaryExpression({ operator: "!" }) || | ||
parentPath.isLoop({ test: node }) | ||
); | ||
} |
119 changes: 119 additions & 0 deletions
119
...posal-class-properties/test/fixtures/private-loose/optional-chain-cast-to-boolean/exec.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
class C { | ||
static #a = { | ||
b: { | ||
c: { | ||
d: 2, | ||
}, | ||
}, | ||
}; | ||
static testIf(o) { | ||
if (o?.#a.b.c.d) { | ||
return true; | ||
} | ||
return false; | ||
} | ||
static testConditional(o) { | ||
return o?.#a.b?.c.d ? true : false; | ||
} | ||
static testLoop(o) { | ||
while (o?.#a.b.c.d) { | ||
for (; o?.#a.b.c?.d; ) { | ||
let i = 0; | ||
do { | ||
i++; | ||
if (i === 2) { | ||
return true; | ||
} | ||
} while (o?.#a.b?.c.d); | ||
} | ||
} | ||
return false; | ||
} | ||
static testNegate(o) { | ||
return !!o?.#a.b?.c.d; | ||
} | ||
static testIfDeep(o) { | ||
if (o.obj?.#a.b?.c.d) { | ||
return true; | ||
} | ||
return false; | ||
} | ||
static testConditionalDeep(o) { | ||
return o.obj?.#a.b?.c.d ? true : false; | ||
} | ||
static testLoopDeep(o) { | ||
while (o.obj?.#a.b.c.d) { | ||
for (; o.obj?.#a.b.c?.d; ) { | ||
let i = 0; | ||
do { | ||
i++; | ||
if (i === 2) { | ||
return true; | ||
} | ||
} while (o.obj?.#a.b?.c.d); | ||
} | ||
} | ||
return false; | ||
} | ||
static testNegateDeep(o) { | ||
return !!o.obj?.#a.b?.c.d; | ||
} | ||
|
||
static testLogicalInIf(o) { | ||
if (o?.#a.b?.c.d && o?.#a?.b.c.d) { | ||
return true; | ||
} | ||
return false; | ||
} | ||
|
||
static testLogicalInReturn(o) { | ||
return o?.#a.b?.c.d && o?.#a?.b.c.d; | ||
} | ||
|
||
static testNullishCoalescing(o) { | ||
if (o?.#a.b?.c.non_existent ?? o?.#a.b?.c.d) { | ||
return o?.#a.b?.c.non_existent ?? o?.#a.b?.c.d; | ||
} | ||
return o?.#a.b?.c.non_existent ?? o; | ||
} | ||
|
||
static test() { | ||
const c = C; | ||
expect(C.testIf(c)).toBe(true); | ||
expect(C.testConditional(c)).toBe(true); | ||
expect(C.testLoop(c)).toBe(true); | ||
expect(C.testNegate(c)).toBe(true); | ||
|
||
expect(C.testIfDeep({ obj: c })).toBe(true); | ||
expect(C.testConditionalDeep({ obj: c })).toBe(true); | ||
expect(C.testLoopDeep({ obj: c })).toBe(true); | ||
expect(C.testNegateDeep({ obj: c })).toBe(true); | ||
|
||
expect(C.testLogicalInIf(c)).toBe(true); | ||
expect(C.testLogicalInReturn(c)).toBe(2); | ||
|
||
expect(C.testNullishCoalescing(c)).toBe(2); | ||
} | ||
|
||
static testNullish() { | ||
for (const n of [null, undefined]) { | ||
expect(C.testIf(n)).toBe(false); | ||
expect(C.testConditional(n)).toBe(false); | ||
expect(C.testLoop(n)).toBe(false); | ||
expect(C.testNegate(n)).toBe(false); | ||
|
||
expect(C.testIfDeep({ obj: n })).toBe(false); | ||
expect(C.testConditionalDeep({ obj: n })).toBe(false); | ||
expect(C.testLoopDeep({ obj: n })).toBe(false); | ||
expect(C.testNegateDeep({ obj: n })).toBe(false); | ||
|
||
expect(C.testLogicalInIf(n)).toBe(false); | ||
expect(C.testLogicalInReturn(n)).toBe(undefined); | ||
|
||
expect(C.testNullishCoalescing(n)).toBe(n); | ||
} | ||
} | ||
} | ||
|
||
C.test(); | ||
C.testNullish(); |
Oops, something went wrong.