Skip to content

Commit 2d7f09d

Browse files
author
Esben Sparre Andreasen
committed
JS(ql): support nullish coalescing operators
1 parent a2a798e commit 2d7f09d

File tree

6 files changed

+64
-1
lines changed

6 files changed

+64
-1
lines changed

javascript/ql/src/semmle/javascript/Expr.qll

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1288,14 +1288,24 @@ class LogOrExpr extends @logorexpr, BinaryExpr {
12881288
override ControlFlowNode getFirstControlFlowNode() { result = this }
12891289
}
12901290

1291+
/** A nullish coalescing '??' expression. */
1292+
class NullishCoalescingExpr extends @nullishcoalescingexpr, BinaryExpr {
1293+
override string getOperator() {
1294+
result = "??"
1295+
}
1296+
1297+
override ControlFlowNode getFirstControlFlowNode() { result = this }
1298+
}
1299+
12911300
/**
12921301
* A logical binary expression, that is, either a logical
12931302
* 'or' or a logical 'and' expression.
12941303
*/
12951304
class LogicalBinaryExpr extends BinaryExpr {
12961305
LogicalBinaryExpr() {
12971306
this instanceof LogAndExpr or
1298-
this instanceof LogOrExpr
1307+
this instanceof LogOrExpr or
1308+
this instanceof NullishCoalescingExpr
12991309
}
13001310
}
13011311

javascript/ql/test/library-tests/DataFlow/flowStep.expected

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
| tst.js:4:5:4:12 | y | tst.js:12:6:12:6 | y |
2626
| tst.js:4:5:4:12 | y | tst.js:13:5:13:5 | y |
2727
| tst.js:4:5:4:12 | y | tst.js:14:9:14:9 | y |
28+
| tst.js:4:5:4:12 | y | tst.js:105:6:105:6 | y |
2829
| tst.js:4:9:4:12 | "hi" | tst.js:4:5:4:12 | y |
2930
| tst.js:9:2:9:2 | x | tst.js:9:1:9:3 | (x) |
3031
| tst.js:10:4:10:4 | y | tst.js:10:1:10:4 | x, y |
@@ -59,6 +60,7 @@
5960
| tst.js:25:1:25:3 | x | tst.js:32:1:32:0 | x |
6061
| tst.js:25:1:25:3 | x | tst.js:57:7:57:7 | x |
6162
| tst.js:25:1:25:3 | x | tst.js:58:11:58:11 | x |
63+
| tst.js:25:1:25:3 | x | tst.js:105:1:105:1 | x |
6264
| tst.js:28:2:28:1 | x | tst.js:29:3:29:3 | x |
6365
| tst.js:28:2:29:3 | () =>\\n x | tst.js:28:1:30:1 | (() =>\\n ... ables\\n) |
6466
| tst.js:29:3:29:3 | x | tst.js:28:1:30:3 | (() =>\\n ... les\\n)() |
@@ -117,6 +119,8 @@
117119
| tst.js:101:13:101:16 | rest | tst.js:101:3:101:16 | [ , z ] = rest |
118120
| tst.js:102:10:102:18 | x + y + z | tst.js:98:1:103:17 | (functi ... 3, 0 ]) |
119121
| tst.js:103:4:103:16 | [ 19, 23, 0 ] | tst.js:98:11:98:24 | [ x, ...rest ] |
122+
| tst.js:105:1:105:1 | x | tst.js:105:1:105:6 | x ?? y |
123+
| tst.js:105:6:105:6 | y | tst.js:105:1:105:6 | x ?? y |
120124
| tst.ts:1:1:1:1 | A | tst.ts:1:11:1:11 | A |
121125
| tst.ts:1:1:1:1 | A | tst.ts:7:1:7:0 | A |
122126
| tst.ts:1:1:5:1 | A | tst.ts:7:1:7:0 | A |

javascript/ql/test/library-tests/DataFlow/tst.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,4 +102,5 @@ var vs2 = ( for (v of o) v ); // generator comprehensions are not analysed
102102
return x + y + z;
103103
})([ 19, 23, 0 ]);
104104

105+
x ?? y; // flow through short-circuiting operator
105106
// semmle-extractor-options: --experimental
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
| v1 | file://:0:0:0:0 | true |
2+
| v2 | file://:0:0:0:0 | false |
3+
| v2 | file://:0:0:0:0 | undefined |
4+
| v4 | file://:0:0:0:0 | false |
5+
| v4 | file://:0:0:0:0 | true |
6+
| v4 | file://:0:0:0:0 | undefined |
7+
| v5 | file://:0:0:0:0 | false |
8+
| v5 | file://:0:0:0:0 | true |
9+
| v5 | file://:0:0:0:0 | undefined |
10+
| v6 | file://:0:0:0:0 | false |
11+
| v6 | file://:0:0:0:0 | true |
12+
| v6 | file://:0:0:0:0 | undefined |
13+
| v7 | file://:0:0:0:0 | false |
14+
| v7 | file://:0:0:0:0 | true |
15+
| v7 | file://:0:0:0:0 | undefined |
16+
| v7 | tst.js:22:15:22:16 | object literal |
17+
| x | file://:0:0:0:0 | false |
18+
| x | file://:0:0:0:0 | true |
19+
| x | file://:0:0:0:0 | undefined |
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import javascript
2+
3+
from Variable v, Expr e
4+
where e = v.getAnAssignedExpr()
5+
select v, e.analyze().getAValue()
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
(function() {
2+
var x = f()? undefined: f()? false: true;
3+
4+
if (x || false) {
5+
v1 = x;
6+
} else {
7+
v2 = x;
8+
}
9+
10+
if (x && false) {
11+
v3 = x;
12+
} else {
13+
v4 = x;
14+
}
15+
16+
if (x ?? false) {
17+
v5 = x;
18+
} else {
19+
v6 = x;
20+
}
21+
22+
v7 = x ?? {};
23+
});
24+
// semmle-extractor-options: --experimental

0 commit comments

Comments
 (0)