@@ -169,7 +169,7 @@ pp.parseExprOps = function(noIn, refDestructuringErrors) {
169
169
let startPos = this . start , startLoc = this . startLoc
170
170
let expr = this . parseMaybeUnary ( refDestructuringErrors , false )
171
171
if ( this . checkExpressionErrors ( refDestructuringErrors ) ) return expr
172
- return expr . start === startPos && expr . type === "ArrowFunctionExpression" ? expr : this . parseExprOp ( expr , startPos , startLoc , - 1 , noIn )
172
+ return expr . start === startPos && expr . type === "ArrowFunctionExpression" ? expr : this . parseExprOp ( expr , startPos , startLoc , - 1 , noIn , 0 )
173
173
}
174
174
175
175
// Parse binary operators with the operator precedence parsing
@@ -178,17 +178,28 @@ pp.parseExprOps = function(noIn, refDestructuringErrors) {
178
178
// defer further parser to one of its callers when it encounters an
179
179
// operator that has a lower precedence than the set it is parsing.
180
180
181
- pp . parseExprOp = function ( left , leftStartPos , leftStartLoc , minPrec , noIn ) {
181
+ // shortCircuitOps:
182
+ // * 1 = only `||` and `&&` are allowed
183
+ // * 2 = only `??` is allowed
184
+ // * others = all
185
+
186
+ pp . parseExprOp = function ( left , leftStartPos , leftStartLoc , minPrec , noIn , shortCircuitOps ) {
182
187
let prec = this . type . binop
183
188
if ( prec != null && ( ! noIn || this . type !== tt . _in ) ) {
189
+ let logical = this . type === tt . logicalOR || this . type === tt . logicalAND
190
+ let coalesce = this . type === tt . coalesce
191
+ if ( shortCircuitOps === 1 && coalesce || shortCircuitOps === 2 && logical ) {
192
+ this . raiseRecoverable ( this . start , "Logical expressions and coalesce expressions cannot be mixed. Wrap either by parentheses" )
193
+ }
194
+ shortCircuitOps = shortCircuitOps || ( logical ? 1 : coalesce ? 2 : 0 )
195
+
184
196
if ( prec > minPrec ) {
185
- let logical = this . type === tt . logicalOR || this . type === tt . logicalAND
186
197
let op = this . value
187
198
this . next ( )
188
199
let startPos = this . start , startLoc = this . startLoc
189
- let right = this . parseExprOp ( this . parseMaybeUnary ( null , false ) , startPos , startLoc , prec , noIn )
190
- let node = this . buildBinary ( leftStartPos , leftStartLoc , left , right , op , logical )
191
- return this . parseExprOp ( node , leftStartPos , leftStartLoc , minPrec , noIn )
200
+ let right = this . parseExprOp ( this . parseMaybeUnary ( null , false ) , startPos , startLoc , prec , noIn , shortCircuitOps )
201
+ let node = this . buildBinary ( leftStartPos , leftStartLoc , left , right , op , logical || coalesce )
202
+ return this . parseExprOp ( node , leftStartPos , leftStartLoc , minPrec , noIn , shortCircuitOps )
192
203
}
193
204
}
194
205
return left
0 commit comments