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;
}
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;
}
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;
}
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;
}
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());
}
}
Aggregations