(expr *js.CondExpr, prec js.OpPrec)
| 801 | } |
| 802 | |
| 803 | func (m *jsMinifier) optimizeCondExpr(expr *js.CondExpr, prec js.OpPrec) js.IExpr { |
| 804 | // remove double negative !! in condition, or switch cases for single negative ! |
| 805 | if unary1, ok := expr.Cond.(*js.UnaryExpr); ok && unary1.Op == js.NotToken { |
| 806 | if unary2, ok := unary1.X.(*js.UnaryExpr); ok && unary2.Op == js.NotToken { |
| 807 | if isBooleanExpr(unary2.X) { |
| 808 | expr.Cond = unary2.X |
| 809 | } |
| 810 | } else { |
| 811 | expr.Cond = unary1.X |
| 812 | expr.X, expr.Y = expr.Y, expr.X |
| 813 | } |
| 814 | } |
| 815 | |
| 816 | finalCond := finalExpr(expr.Cond) |
| 817 | if truthy, ok := isTruthy(expr.Cond); truthy && ok { |
| 818 | // if condition is truthy |
| 819 | return expr.X |
| 820 | } else if !truthy && ok { |
| 821 | // if condition is falsy |
| 822 | return expr.Y |
| 823 | } else if isEqualExpr(finalCond, expr.X) && (exprPrec(finalCond) < js.OpAssign || binaryLeftPrecMap[js.OrToken] <= exprPrec(finalCond)) && (exprPrec(expr.Y) < js.OpAssign || binaryRightPrecMap[js.OrToken] <= exprPrec(expr.Y)) { |
| 824 | // if condition is equal to true body |
| 825 | // for higher prec we need to add group parenthesis, and for lower prec we have parenthesis anyways. This only is shorter if len(expr.X) >= 3. isEqualExpr only checks for literal variables, which is a name will be minified to a one or two character name. |
| 826 | return &js.BinaryExpr{js.OrToken, groupExpr(expr.Cond, binaryLeftPrecMap[js.OrToken]), expr.Y} |
| 827 | } else if isEqualExpr(finalCond, expr.Y) && (exprPrec(finalCond) < js.OpAssign || binaryLeftPrecMap[js.AndToken] <= exprPrec(finalCond)) && (exprPrec(expr.X) < js.OpAssign || binaryRightPrecMap[js.AndToken] <= exprPrec(expr.X)) { |
| 828 | // if condition is equal to false body |
| 829 | // for higher prec we need to add group parenthesis, and for lower prec we have parenthesis anyways. This only is shorter if len(expr.X) >= 3. isEqualExpr only checks for literal variables, which is a name will be minified to a one or two character name. |
| 830 | return &js.BinaryExpr{js.AndToken, groupExpr(expr.Cond, binaryLeftPrecMap[js.AndToken]), expr.X} |
| 831 | } else if isEqualExpr(expr.X, expr.Y) { |
| 832 | // if true and false bodies are equal |
| 833 | return groupExpr(&js.CommaExpr{[]js.IExpr{expr.Cond, expr.X}}, prec) |
| 834 | } else { |
| 835 | if m.o.minVersion(2020) { |
| 836 | if nullishExpr, ok := toNullishExpr(expr); ok { |
| 837 | // no need to check whether left/right need to add groups, as the space saving is always more |
| 838 | return nullishExpr |
| 839 | } |
| 840 | } |
| 841 | callX, isCallX := expr.X.(*js.CallExpr) |
| 842 | callY, isCallY := expr.Y.(*js.CallExpr) |
| 843 | if isCallX && isCallY && len(callX.Args.List) == 1 && len(callY.Args.List) == 1 && !callX.Args.List[0].Rest && !callY.Args.List[0].Rest && isEqualExpr(callX.X, callY.X) { |
| 844 | expr.X = callX.Args.List[0].Value |
| 845 | expr.Y = callY.Args.List[0].Value |
| 846 | return &js.CallExpr{callX.X, js.Args{[]js.Arg{{expr, false}}}, js.OpCall, false} // recompress the conditional expression inside |
| 847 | } |
| 848 | |
| 849 | // shorten when true and false bodies are true and false |
| 850 | trueX, falseX := isTrue(expr.X), isFalse(expr.X) |
| 851 | trueY, falseY := isTrue(expr.Y), isFalse(expr.Y) |
| 852 | if trueX && falseY || falseX && trueY { |
| 853 | return optimizeBooleanExpr(expr.Cond, falseX, prec) |
| 854 | } else if trueX || trueY { |
| 855 | // trueX != trueY |
| 856 | cond := optimizeBooleanExpr(expr.Cond, trueY, binaryLeftPrecMap[js.OrToken]) |
| 857 | if trueY { |
| 858 | return &js.BinaryExpr{js.OrToken, cond, groupExpr(expr.X, binaryRightPrecMap[js.OrToken])} |
| 859 | } else { |
| 860 | return &js.BinaryExpr{js.OrToken, cond, groupExpr(expr.Y, binaryRightPrecMap[js.OrToken])} |
no test coverage detected