Skip to content

Commit 76afa8e

Browse files
rishipalcopybara-github
authored andcommitted
Add reaching definition analysis for Optional Chaining
PiperOrigin-RevId: 321995452
1 parent 7fa6021 commit 76afa8e

File tree

2 files changed

+31
-6
lines changed

2 files changed

+31
-6
lines changed

src/com/google/javascript/jscomp/MustBeReachingVariableDef.java

+10-4
Original file line numberDiff line numberDiff line change
@@ -247,14 +247,11 @@ private void computeMustDef(
247247
case WHILE:
248248
case DO:
249249
case IF:
250+
case FOR:
250251
computeMustDef(
251252
NodeUtil.getConditionExpression(n), cfgNode, output, conditional);
252253
return;
253254

254-
case FOR:
255-
computeMustDef(NodeUtil.getConditionExpression(n), cfgNode, output, conditional);
256-
return;
257-
258255
case FOR_IN:
259256
case FOR_OF:
260257
case FOR_AWAIT_OF:
@@ -278,10 +275,19 @@ private void computeMustDef(
278275
case AND:
279276
case OR:
280277
case COALESCE:
278+
case OPTCHAIN_GETPROP:
279+
case OPTCHAIN_GETELEM:
281280
computeMustDef(n.getFirstChild(), cfgNode, output, conditional);
282281
computeMustDef(n.getLastChild(), cfgNode, output, true);
283282
return;
284283

284+
case OPTCHAIN_CALL:
285+
computeMustDef(n.getFirstChild(), cfgNode, output, conditional);
286+
for (Node c = n.getSecondChild(); c != null; c = c.getNext()) {
287+
computeMustDef(c, cfgNode, output, true);
288+
}
289+
return;
290+
285291
case HOOK:
286292
computeMustDef(n.getFirstChild(), cfgNode, output, conditional);
287293
computeMustDef(n.getSecondChild(), cfgNode, output, true);

test/com/google/javascript/jscomp/MustBeReachingVariableDefTest.java

+21-2
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
/**
3232
* Tests for {@link MustBeReachingVariableDef}.
3333
*
34+
* <p>Tests in this class look for the labels 'D:' and 'U:' in the input code and check whether the
35+
* definition of a var `x` at label `D:` is the must-reaching definition for its use at label `U:`.
3436
*/
3537
@RunWith(JUnit4.class)
3638
public final class MustBeReachingVariableDefTest {
@@ -76,14 +78,31 @@ public void testLoops() {
7678
public void testConditional() {
7779
assertMatch("var x=0,y; D:(x=1)&&y; U:x");
7880
assertNotMatch("var x=0,y; D:y&&(x=1); U:x");
81+
assertNotMatch("D:var x=0; var y; y&&(x=1); U:x");
7982
}
8083

8184
@Test
8285
public void nullishCoalesce() {
83-
// LHS is always executed so the definition of x = 1 must be reached
86+
// LHS is always executed so the definition of x = 1 must be reached
8487
assertMatch("var x=0,y; D:(x=1)??y; U:x");
8588
// definitions in RHS are not always executed
86-
assertNotMatch("var x=0,y; D:y??(x=1); U:x");
89+
assertNotMatch("var x=0; var y; D:y??(x=1); U:x");
90+
assertNotMatch("D:var x=0; var y; y??(x=1); U:x");
91+
}
92+
93+
@Test
94+
public void optionalChaining() {
95+
// LHS is always executed so the definition of x = 1 must be reached
96+
assertMatch("var x=0,y; D:(x=1)?.y; U:x");
97+
assertMatch("var x=0,y; D:(x=1)?.[y]; U:x");
98+
assertMatch("var x=0,y; D:(x=1)?.(y); U:x");
99+
assertMatch("var x=0,y,z; D:z(x=1)?.y; U:x");
100+
assertMatch("var x=0,y,z; D:z[x=1]?.y; U:x");
101+
102+
// definitions in RHS are not always executed
103+
assertNotMatch("var x = 0,y; D:y?.(x=1); U:x");
104+
assertNotMatch("D:var x = 0; var y; y?.(x=1); U:x");
105+
assertNotMatch("var x=0,y; D:y?.[x=1]; U:x");
87106
}
88107

89108
@Test

0 commit comments

Comments
 (0)