Search in sources :

Example 1 with ValueType

use of com.google.javascript.jscomp.NodeUtil.ValueType in project closure-compiler by google.

the class PeepholeFoldConstants method tryStrictEqualityComparison.

/**
 * http://www.ecma-international.org/ecma-262/6.0/#sec-strict-equality-comparison
 */
private static TernaryValue tryStrictEqualityComparison(Node left, Node right) {
    // First, try to evaluate based on the general type.
    ValueType leftValueType = NodeUtil.getKnownValueType(left);
    ValueType rightValueType = NodeUtil.getKnownValueType(right);
    if (leftValueType != ValueType.UNDETERMINED && rightValueType != ValueType.UNDETERMINED) {
        // Strict equality can only be true for values of the same type.
        if (leftValueType != rightValueType) {
            return TernaryValue.FALSE;
        }
        switch(leftValueType) {
            case VOID:
            case NULL:
                return TernaryValue.TRUE;
            case NUMBER:
                {
                    if (NodeUtil.isNaN(left)) {
                        return TernaryValue.FALSE;
                    }
                    if (NodeUtil.isNaN(right)) {
                        return TernaryValue.FALSE;
                    }
                    Double lv = NodeUtil.getNumberValue(left);
                    Double rv = NodeUtil.getNumberValue(right);
                    if (lv != null && rv != null) {
                        return TernaryValue.forBoolean(lv.doubleValue() == rv.doubleValue());
                    }
                    break;
                }
            case STRING:
                {
                    String lv = NodeUtil.getStringValue(left);
                    String rv = NodeUtil.getStringValue(right);
                    if (lv != null && rv != null) {
                        // equal if one contains \v.
                        if (lv.indexOf('\u000B') != -1 || rv.indexOf('\u000B') != -1) {
                            return TernaryValue.UNKNOWN;
                        } else {
                            return lv.equals(rv) ? TernaryValue.TRUE : TernaryValue.FALSE;
                        }
                    } else if (left.isTypeOf() && right.isTypeOf() && left.getFirstChild().isName() && right.getFirstChild().isName() && left.getFirstChild().getString().equals(right.getFirstChild().getString())) {
                        // Special case, typeof a == typeof a is always true.
                        return TernaryValue.TRUE;
                    }
                    break;
                }
            case BOOLEAN:
                {
                    TernaryValue lv = NodeUtil.getPureBooleanValue(left);
                    TernaryValue rv = NodeUtil.getPureBooleanValue(right);
                    return lv.and(rv).or(lv.not().and(rv.not()));
                }
            default:
                // Symbol and Object cannot be folded in the general case.
                return TernaryValue.UNKNOWN;
        }
    }
    // Any strict equality comparison against NaN returns false.
    if (NodeUtil.isNaN(left) || NodeUtil.isNaN(right)) {
        return TernaryValue.FALSE;
    }
    return TernaryValue.UNKNOWN;
}
Also used : ValueType(com.google.javascript.jscomp.NodeUtil.ValueType) TernaryValue(com.google.javascript.rhino.jstype.TernaryValue)

Example 2 with ValueType

use of com.google.javascript.jscomp.NodeUtil.ValueType in project closure-compiler by google.

the class PeepholeFoldConstants method tryAbstractEqualityComparison.

/**
 * http://www.ecma-international.org/ecma-262/6.0/#sec-abstract-equality-comparison
 */
private static TernaryValue tryAbstractEqualityComparison(Node left, Node right) {
    // Evaluate based on the general type.
    ValueType leftValueType = NodeUtil.getKnownValueType(left);
    ValueType rightValueType = NodeUtil.getKnownValueType(right);
    if (leftValueType != ValueType.UNDETERMINED && rightValueType != ValueType.UNDETERMINED) {
        // Delegate to strict equality comparison for values of the same type.
        if (leftValueType == rightValueType) {
            return tryStrictEqualityComparison(left, right);
        }
        if ((leftValueType == ValueType.NULL && rightValueType == ValueType.VOID) || (leftValueType == ValueType.VOID && rightValueType == ValueType.NULL)) {
            return TernaryValue.TRUE;
        }
        if ((leftValueType == ValueType.NUMBER && rightValueType == ValueType.STRING) || rightValueType == ValueType.BOOLEAN) {
            Double rv = NodeUtil.getNumberValue(right);
            return rv == null ? TernaryValue.UNKNOWN : tryAbstractEqualityComparison(left, IR.number(rv));
        }
        if ((leftValueType == ValueType.STRING && rightValueType == ValueType.NUMBER) || leftValueType == ValueType.BOOLEAN) {
            Double lv = NodeUtil.getNumberValue(left);
            return lv == null ? TernaryValue.UNKNOWN : tryAbstractEqualityComparison(IR.number(lv), right);
        }
        if ((leftValueType == ValueType.STRING || leftValueType == ValueType.NUMBER) && rightValueType == ValueType.OBJECT) {
            return TernaryValue.UNKNOWN;
        }
        if (leftValueType == ValueType.OBJECT && (rightValueType == ValueType.STRING || rightValueType == ValueType.NUMBER)) {
            return TernaryValue.UNKNOWN;
        }
        return TernaryValue.FALSE;
    }
    // In general, the rest of the cases cannot be folded.
    return TernaryValue.UNKNOWN;
}
Also used : ValueType(com.google.javascript.jscomp.NodeUtil.ValueType)

Example 3 with ValueType

use of com.google.javascript.jscomp.NodeUtil.ValueType in project closure-compiler by google.

the class PeepholeFoldConstants method tryStrictEqualityComparison.

/**
 * http://www.ecma-international.org/ecma-262/6.0/#sec-strict-equality-comparison
 */
private static Tri tryStrictEqualityComparison(AbstractPeepholeOptimization peepholeOptimization, Node left, Node right) {
    // First, try to evaluate based on the general type.
    ValueType leftValueType = NodeUtil.getKnownValueType(left);
    ValueType rightValueType = NodeUtil.getKnownValueType(right);
    if (leftValueType != ValueType.UNDETERMINED && rightValueType != ValueType.UNDETERMINED) {
        // Strict equality can only be true for values of the same type.
        if (leftValueType != rightValueType) {
            return Tri.FALSE;
        }
        switch(leftValueType) {
            case VOID:
            case NULL:
                return Tri.TRUE;
            case NUMBER:
                {
                    if (NodeUtil.isNaN(left)) {
                        return Tri.FALSE;
                    }
                    if (NodeUtil.isNaN(right)) {
                        return Tri.FALSE;
                    }
                    Double lv = peepholeOptimization.getSideEffectFreeNumberValue(left);
                    Double rv = peepholeOptimization.getSideEffectFreeNumberValue(right);
                    if (lv != null && rv != null) {
                        return Tri.forBoolean(lv.doubleValue() == rv.doubleValue());
                    }
                    break;
                }
            case STRING:
                {
                    String lv = peepholeOptimization.getSideEffectFreeStringValue(left);
                    String rv = peepholeOptimization.getSideEffectFreeStringValue(right);
                    if (lv != null && rv != null) {
                        // equal if one contains \v.
                        if (lv.indexOf('\u000B') != -1 || rv.indexOf('\u000B') != -1) {
                            return Tri.UNKNOWN;
                        } else {
                            return lv.equals(rv) ? Tri.TRUE : Tri.FALSE;
                        }
                    } else if (left.isTypeOf() && right.isTypeOf() && left.getFirstChild().isName() && right.getFirstChild().isName() && left.getFirstChild().getString().equals(right.getFirstChild().getString())) {
                        // Special case, typeof a == typeof a is always true.
                        return Tri.TRUE;
                    }
                    break;
                }
            case BOOLEAN:
                {
                    Tri lv = peepholeOptimization.getSideEffectFreeBooleanValue(left);
                    Tri rv = peepholeOptimization.getSideEffectFreeBooleanValue(right);
                    return lv.and(rv).or(lv.not().and(rv.not()));
                }
            case BIGINT:
                {
                    BigInteger lv = peepholeOptimization.getSideEffectFreeBigIntValue(left);
                    BigInteger rv = peepholeOptimization.getSideEffectFreeBigIntValue(right);
                    return Tri.forBoolean(lv.equals(rv));
                }
            default:
                // Symbol and Object cannot be folded in the general case.
                return Tri.UNKNOWN;
        }
    }
    // Any strict equality comparison against NaN returns false.
    if (NodeUtil.isNaN(left) || NodeUtil.isNaN(right)) {
        return Tri.FALSE;
    }
    return Tri.UNKNOWN;
}
Also used : ValueType(com.google.javascript.jscomp.NodeUtil.ValueType) BigInteger(java.math.BigInteger) Tri(com.google.javascript.jscomp.base.Tri)

Example 4 with ValueType

use of com.google.javascript.jscomp.NodeUtil.ValueType in project closure-compiler by google.

the class PeepholeFoldConstants method tryAbstractRelationalComparison.

/**
 * https://tc39.es/ecma262/#sec-abstract-relational-comparison
 */
private static Tri tryAbstractRelationalComparison(AbstractPeepholeOptimization peepholeOptimization, Node left, Node right, boolean willNegate) {
    ValueType leftValueType = NodeUtil.getKnownValueType(left);
    ValueType rightValueType = NodeUtil.getKnownValueType(right);
    // First, check for a string comparison.
    if (leftValueType == ValueType.STRING && rightValueType == ValueType.STRING) {
        String lvStr = peepholeOptimization.getSideEffectFreeStringValue(left);
        String rvStr = peepholeOptimization.getSideEffectFreeStringValue(right);
        if (lvStr != null && rvStr != null) {
            // In JS, browsers parse \v differently. So do not compare strings if one contains \v.
            if (lvStr.indexOf('\u000B') != -1 || rvStr.indexOf('\u000B') != -1) {
                return Tri.UNKNOWN;
            } else {
                return Tri.forBoolean(lvStr.compareTo(rvStr) < 0);
            }
        } else if (left.isTypeOf() && right.isTypeOf() && left.getFirstChild().isName() && right.getFirstChild().isName() && left.getFirstChild().getString().equals(right.getFirstChild().getString())) {
            // Special case: `typeof a < typeof a` is always false.
            return Tri.FALSE;
        }
    }
    // Next, try to evaluate based on the value of the node. Try comparing as BigInts first.
    BigInteger lvBig = peepholeOptimization.getSideEffectFreeBigIntValue(left);
    BigInteger rvBig = peepholeOptimization.getSideEffectFreeBigIntValue(right);
    if (lvBig != null && rvBig != null) {
        return Tri.forBoolean(lvBig.compareTo(rvBig) < 0);
    }
    // Then, try comparing as Numbers.
    Double lvNum = peepholeOptimization.getSideEffectFreeNumberValue(left);
    Double rvNum = peepholeOptimization.getSideEffectFreeNumberValue(right);
    if (lvNum != null && rvNum != null) {
        if (Double.isNaN(lvNum) || Double.isNaN(rvNum)) {
            return Tri.forBoolean(willNegate);
        } else {
            return Tri.forBoolean(lvNum.doubleValue() < rvNum.doubleValue());
        }
    }
    // Finally, try comparisons between BigInt and Number.
    if (lvBig != null && rvNum != null) {
        return bigintLessThanDouble(lvBig, rvNum, Tri.FALSE, willNegate);
    }
    if (lvNum != null && rvBig != null) {
        return bigintLessThanDouble(rvBig, lvNum, Tri.TRUE, willNegate);
    }
    // LE and GE. We should use type information if available here.
    if (!willNegate && left.isName() && right.isName()) {
        if (left.getString().equals(right.getString())) {
            return Tri.FALSE;
        }
    }
    return Tri.UNKNOWN;
}
Also used : ValueType(com.google.javascript.jscomp.NodeUtil.ValueType) BigInteger(java.math.BigInteger)

Example 5 with ValueType

use of com.google.javascript.jscomp.NodeUtil.ValueType in project closure-compiler by google.

the class PeepholeFoldConstants method tryAbstractRelationalComparison.

/**
 * http://www.ecma-international.org/ecma-262/6.0/#sec-abstract-relational-comparison
 */
private static TernaryValue tryAbstractRelationalComparison(Node left, Node right, boolean willNegate) {
    // First, try to evaluate based on the general type.
    ValueType leftValueType = NodeUtil.getKnownValueType(left);
    ValueType rightValueType = NodeUtil.getKnownValueType(right);
    if (leftValueType != ValueType.UNDETERMINED && rightValueType != ValueType.UNDETERMINED) {
        if (leftValueType == ValueType.STRING && rightValueType == ValueType.STRING) {
            String lv = NodeUtil.getStringValue(left);
            String rv = NodeUtil.getStringValue(right);
            if (lv != null && rv != null) {
                // In JS, browsers parse \v differently. So do not compare strings if one contains \v.
                if (lv.indexOf('\u000B') != -1 || rv.indexOf('\u000B') != -1) {
                    return TernaryValue.UNKNOWN;
                } else {
                    return TernaryValue.forBoolean(lv.compareTo(rv) < 0);
                }
            } else if (left.isTypeOf() && right.isTypeOf() && left.getFirstChild().isName() && right.getFirstChild().isName() && left.getFirstChild().getString().equals(right.getFirstChild().getString())) {
                // Special case: `typeof a < typeof a` is always false.
                return TernaryValue.FALSE;
            }
        }
    }
    // Then, try to evaluate based on the value of the node. Try comparing as numbers.
    Double lv = NodeUtil.getNumberValue(left);
    Double rv = NodeUtil.getNumberValue(right);
    if (lv == null || rv == null) {
        // LE and GE. We should use type information if available here.
        if (!willNegate && left.isName() && right.isName()) {
            if (left.getString().equals(right.getString())) {
                return TernaryValue.FALSE;
            }
        }
        return TernaryValue.UNKNOWN;
    }
    if (Double.isNaN(lv) || Double.isNaN(rv)) {
        return TernaryValue.forBoolean(willNegate);
    } else {
        return TernaryValue.forBoolean(lv.doubleValue() < rv.doubleValue());
    }
}
Also used : ValueType(com.google.javascript.jscomp.NodeUtil.ValueType)

Aggregations

ValueType (com.google.javascript.jscomp.NodeUtil.ValueType)6 BigInteger (java.math.BigInteger)3 Tri (com.google.javascript.jscomp.base.Tri)1 TernaryValue (com.google.javascript.rhino.jstype.TernaryValue)1