diff --git a/src/com/google/javascript/jscomp/DefaultPassConfig.java b/src/com/google/javascript/jscomp/DefaultPassConfig.java index ad026bb0f18..5fe9149dbd0 100644 --- a/src/com/google/javascript/jscomp/DefaultPassConfig.java +++ b/src/com/google/javascript/jscomp/DefaultPassConfig.java @@ -1723,7 +1723,7 @@ private static CompilerPass createPeepholeOptimizationsPass( final boolean useTypesForOptimization = compiler.getOptions().useTypesForLocalOptimization; List optimizations = new ArrayList<>(); optimizations.add(new MinimizeExitPoints(compiler)); - optimizations.add(new PeepholeMinimizeConditions(late, useTypesForOptimization)); + optimizations.add(new PeepholeMinimizeConditions(late)); optimizations.add(new PeepholeSubstituteAlternateSyntax(late)); optimizations.add(new PeepholeReplaceKnownMethods(late, useTypesForOptimization)); optimizations.add(new PeepholeRemoveDeadCode()); @@ -1775,7 +1775,7 @@ protected CompilerPass create(AbstractCompiler compiler) { getName(), new StatementFusion(options.aggressiveFusion), new PeepholeRemoveDeadCode(), - new PeepholeMinimizeConditions(late, useTypesForOptimization), + new PeepholeMinimizeConditions(late), new PeepholeSubstituteAlternateSyntax(late), new PeepholeReplaceKnownMethods(late, useTypesForOptimization), new PeepholeFoldConstants(late, useTypesForOptimization), diff --git a/src/com/google/javascript/jscomp/NodeUtil.java b/src/com/google/javascript/jscomp/NodeUtil.java index 59bb8f63b4a..e35e069e323 100644 --- a/src/com/google/javascript/jscomp/NodeUtil.java +++ b/src/com/google/javascript/jscomp/NodeUtil.java @@ -298,10 +298,6 @@ static String arrayToString(Node literal) { return result.toString(); } - public static Double getNumberValue(Node n) { - return getNumberValue(n, false); - } - /** * Gets the value of a node as a Number, or null if it cannot be converted. * When it returns a non-null Double, this method effectively emulates the @@ -311,7 +307,7 @@ public static Double getNumberValue(Node n) { * @param useType If true, return 0.0 if the type is null, and NaN if the type is undefined. * @return The value of a node as a Number, or null if it cannot be converted. */ - static Double getNumberValue(Node n, boolean useType) { + static Double getNumberValue(Node n) { switch (n.getToken()) { case TRUE: return 1.0; @@ -342,16 +338,6 @@ static Double getNumberValue(Node n, boolean useType) { if (name.equals("Infinity")) { return Double.POSITIVE_INFINITY; } - if (useType) { - TypeI type = n.getTypeI(); - if (type != null) { - if (type.isVoidType()) { - return Double.NaN; - } else if (type.isNullType()) { - return 0.0; - } - } - } return null; case NEG: diff --git a/src/com/google/javascript/jscomp/PeepholeFoldConstants.java b/src/com/google/javascript/jscomp/PeepholeFoldConstants.java index 07310c08167..1b57e0af095 100644 --- a/src/com/google/javascript/jscomp/PeepholeFoldConstants.java +++ b/src/com/google/javascript/jscomp/PeepholeFoldConstants.java @@ -262,7 +262,7 @@ private void tryConvertToNumber(Node n) { break; } - Double result = NodeUtil.getNumberValue(n, shouldUseTypes); + Double result = NodeUtil.getNumberValue(n); if (result == null) { return; } @@ -739,11 +739,11 @@ private Node performArithmeticOp(Token opType, Node left, Node right) { // TODO(johnlenz): Handle NaN with unknown value. BIT ops convert NaN // to zero so this is a little awkward here. - Double lValObj = NodeUtil.getNumberValue(left, shouldUseTypes); + Double lValObj = NodeUtil.getNumberValue(left); if (lValObj == null) { return null; } - Double rValObj = NodeUtil.getNumberValue(right, shouldUseTypes); + Double rValObj = NodeUtil.getNumberValue(right); if (rValObj == null) { return null; } @@ -819,7 +819,7 @@ private Node tryFoldLeftChildOp(Node n, Node left, Node right) { // Use getNumberValue to handle constants like "NaN" and "Infinity" // other values are converted to numbers elsewhere. - Double rightValObj = NodeUtil.getNumberValue(right, shouldUseTypes); + Double rightValObj = NodeUtil.getNumberValue(right); if (rightValObj != null && left.getToken() == opType) { checkState(left.hasTwoChildren()); @@ -852,8 +852,7 @@ private Node tryFoldAdd(Node node, Node left, Node right) { checkArgument(node.isAdd()); if (NodeUtil.mayBeString(node, shouldUseTypes)) { - if (NodeUtil.isLiteralValue(left, false) && - NodeUtil.isLiteralValue(right, false)) { + if (NodeUtil.isLiteralValue(left, false) && NodeUtil.isLiteralValue(right, false)) { // '6' + 7 return tryFoldAddConstantString(node, left, right); } else { @@ -930,7 +929,7 @@ private Node tryFoldShift(Node n, Node left, Node right) { * Try to fold comparison nodes, e.g == */ private Node tryFoldComparison(Node n, Node left, Node right) { - TernaryValue result = evaluateComparison(n.getToken(), left, right, shouldUseTypes); + TernaryValue result = evaluateComparison(n.getToken(), left, right); if (result == TernaryValue.UNKNOWN) { return n; } @@ -945,7 +944,7 @@ private Node tryFoldComparison(Node n, Node left, Node right) { /** http://www.ecma-international.org/ecma-262/6.0/#sec-abstract-relational-comparison */ private static TernaryValue tryAbstractRelationalComparison(Node left, Node right, - boolean useTypes, boolean willNegate) { + boolean willNegate) { // First, try to evaluate based on the general type. ValueType leftValueType = NodeUtil.getKnownValueType(left); ValueType rightValueType = NodeUtil.getKnownValueType(right); @@ -969,8 +968,8 @@ private static TernaryValue tryAbstractRelationalComparison(Node left, Node righ } } // Then, try to evaluate based on the value of the node. Try comparing as numbers. - Double lv = NodeUtil.getNumberValue(left, useTypes); - Double rv = NodeUtil.getNumberValue(right, useTypes); + Double lv = NodeUtil.getNumberValue(left); + Double rv = NodeUtil.getNumberValue(right); if (lv == null || rv == null) { // Special case: `x < x` is always false. // @@ -991,15 +990,14 @@ private static TernaryValue tryAbstractRelationalComparison(Node left, Node righ } /** http://www.ecma-international.org/ecma-262/6.0/#sec-abstract-equality-comparison */ - private static TernaryValue tryAbstractEqualityComparison(Node left, Node right, - boolean useTypes) { + 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, useTypes); + return tryStrictEqualityComparison(left, right); } if ((leftValueType == ValueType.NULL && rightValueType == ValueType.VOID) || (leftValueType == ValueType.VOID && rightValueType == ValueType.NULL)) { @@ -1007,17 +1005,17 @@ private static TernaryValue tryAbstractEqualityComparison(Node left, Node right, } if ((leftValueType == ValueType.NUMBER && rightValueType == ValueType.STRING) || rightValueType == ValueType.BOOLEAN) { - Double rv = NodeUtil.getNumberValue(right, useTypes); + Double rv = NodeUtil.getNumberValue(right); return rv == null ? TernaryValue.UNKNOWN - : tryAbstractEqualityComparison(left, IR.number(rv), useTypes); + : tryAbstractEqualityComparison(left, IR.number(rv)); } if ((leftValueType == ValueType.STRING && rightValueType == ValueType.NUMBER) || leftValueType == ValueType.BOOLEAN) { - Double lv = NodeUtil.getNumberValue(left, useTypes); + Double lv = NodeUtil.getNumberValue(left); return lv == null ? TernaryValue.UNKNOWN - : tryAbstractEqualityComparison(IR.number(lv), right, useTypes); + : tryAbstractEqualityComparison(IR.number(lv), right); } if ((leftValueType == ValueType.STRING || leftValueType == ValueType.NUMBER) && rightValueType == ValueType.OBJECT) { @@ -1034,7 +1032,7 @@ private static TernaryValue tryAbstractEqualityComparison(Node left, Node right, } /** http://www.ecma-international.org/ecma-262/6.0/#sec-strict-equality-comparison */ - private static TernaryValue tryStrictEqualityComparison(Node left, Node right, boolean useTypes) { + 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); @@ -1054,8 +1052,8 @@ private static TernaryValue tryStrictEqualityComparison(Node left, Node right, b if (NodeUtil.isNaN(right)) { return TernaryValue.FALSE; } - Double lv = NodeUtil.getNumberValue(left, useTypes); - Double rv = NodeUtil.getNumberValue(right, useTypes); + Double lv = NodeUtil.getNumberValue(left); + Double rv = NodeUtil.getNumberValue(right); if (lv != null && rv != null) { return TernaryValue.forBoolean(lv.doubleValue() == rv.doubleValue()); } @@ -1098,7 +1096,7 @@ private static TernaryValue tryStrictEqualityComparison(Node left, Node right, b return TernaryValue.UNKNOWN; } - static TernaryValue evaluateComparison(Token op, Node left, Node right, boolean useTypes) { + static TernaryValue evaluateComparison(Token op, Node left, Node right) { // Don't try to minimize side-effects here. if (NodeUtil.mayHaveSideEffects(left) || NodeUtil.mayHaveSideEffects(right)) { return TernaryValue.UNKNOWN; @@ -1106,21 +1104,21 @@ static TernaryValue evaluateComparison(Token op, Node left, Node right, boolean switch (op) { case EQ: - return tryAbstractEqualityComparison(left, right, useTypes); + return tryAbstractEqualityComparison(left, right); case NE: - return tryAbstractEqualityComparison(left, right, useTypes).not(); + return tryAbstractEqualityComparison(left, right).not(); case SHEQ: - return tryStrictEqualityComparison(left, right, useTypes); + return tryStrictEqualityComparison(left, right); case SHNE: - return tryStrictEqualityComparison(left, right, useTypes).not(); + return tryStrictEqualityComparison(left, right).not(); case LT: - return tryAbstractRelationalComparison(left, right, useTypes, false); + return tryAbstractRelationalComparison(left, right, false); case GT: - return tryAbstractRelationalComparison(right, left, useTypes, false); + return tryAbstractRelationalComparison(right, left, false); case LE: - return tryAbstractRelationalComparison(right, left, useTypes, true).not(); + return tryAbstractRelationalComparison(right, left, true).not(); case GE: - return tryAbstractRelationalComparison(left, right, useTypes, true).not(); + return tryAbstractRelationalComparison(left, right, true).not(); default: break; } diff --git a/src/com/google/javascript/jscomp/PeepholeMinimizeConditions.java b/src/com/google/javascript/jscomp/PeepholeMinimizeConditions.java index 659083c3bde..586591487fd 100644 --- a/src/com/google/javascript/jscomp/PeepholeMinimizeConditions.java +++ b/src/com/google/javascript/jscomp/PeepholeMinimizeConditions.java @@ -26,7 +26,6 @@ import com.google.javascript.rhino.IR; import com.google.javascript.rhino.Node; import com.google.javascript.rhino.Token; -import com.google.javascript.rhino.TypeI; import com.google.javascript.rhino.jstype.TernaryValue; /** @@ -43,7 +42,6 @@ class PeepholeMinimizeConditions private static final int AND_PRECEDENCE = NodeUtil.precedence(Token.AND); private final boolean late; - private final boolean useTypes; /** * @param late When late is false, this mean we are currently running before @@ -52,9 +50,8 @@ class PeepholeMinimizeConditions * merging statements with commas, etc). When this is true, we would * do anything to minimize for size. */ - PeepholeMinimizeConditions(boolean late, boolean useTypes) { + PeepholeMinimizeConditions(boolean late) { this.late = late; - this.useTypes = useTypes; } /** @@ -81,17 +78,14 @@ public Node optimizeSubtree(Node node) { return tryMinimizeNot(node); case IF: - performCoercionSubstitutions(node.getFirstChild()); performConditionSubstitutions(node.getFirstChild()); return tryMinimizeIf(node); case EXPR_RESULT: - performCoercionSubstitutions(node.getFirstChild()); performConditionSubstitutions(node.getFirstChild()); return tryMinimizeExprResult(node); case HOOK: - performCoercionSubstitutions(node.getFirstChild()); performConditionSubstitutions(node.getFirstChild()); return tryMinimizeHook(node); @@ -108,12 +102,6 @@ public Node optimizeSubtree(Node node) { case BLOCK: return tryReplaceIf(node); - case EQ: - case NE: - case SHEQ: - case SHNE: - return tryReplaceComparisonWithCoercion(node, true /* booleanResult */); - default: return node; //Nothing changed } @@ -980,7 +968,6 @@ public boolean apply(Node input) { * @return The replacement for n, or the original if no change was made. */ private Node tryMinimizeCondition(Node n) { - n = performCoercionSubstitutions(n); n = performConditionSubstitutions(n); MinimizedCondition minCond = MinimizedCondition.fromConditionNode(n); return replaceNode( @@ -988,133 +975,6 @@ private Node tryMinimizeCondition(Node n) { minCond.getMinimized(MinimizationStyle.PREFER_UNNEGATED)); } - /** - * Replaces 'foo ==/!=/===/!== null' with 'foo' or '!foo'. Should only be used for expressions - * used in conditions where the final result is coerced to a boolean. - * - * @return The replacement for n, or the original if no change was made. - */ - private Node performCoercionSubstitutions(Node n) { - if (!useTypes) { - return n; - } - - switch (n.getToken()) { - case OR: - case AND: - performCoercionSubstitutions(n.getFirstChild()); - performCoercionSubstitutions(n.getLastChild()); - break; - - case EQ: - case NE: - case SHEQ: - case SHNE: - return tryReplaceComparisonWithCoercion(n, false /* booleanResult */); - default: - break; - } - return n; - } - - /** - * Replaces comparisons (e.g. obj == null, num == 0) with the equivalent type - * coercion (e.g. !obj, !num), if possible. - * @param n a comparison node - * @param booleanResult whether the replacement must evaluate to a boolean - * @return the replacement node or the original node if no replacement was made - */ - private Node tryReplaceComparisonWithCoercion(Node n, boolean booleanResult) { - if (!useTypes) { - return n; - } - - Token op = n.getToken(); - boolean isShallow = op == Token.SHEQ || op == Token.SHNE; - checkArgument(op == Token.EQ || op == Token.NE || isShallow); - - Node left = n.getFirstChild(); - Node right = n.getLastChild(); - BooleanCoercability booleanCoercability = - canConvertComparisonToBooleanCoercion(left, right, isShallow); - if (booleanCoercability != BooleanCoercability.NONE) { - n.detachChildren(); - Node objExpression = booleanCoercability == BooleanCoercability.LEFT ? left : right; - Node replacement; - if (n.getToken() == Token.EQ || n.getToken() == Token.SHEQ) { - replacement = IR.not(objExpression); - } else { - replacement = booleanResult ? IR.not(IR.not(objExpression)).srcrefTree(n) : objExpression; - } - n.replaceWith(replacement); - compiler.reportChangeToEnclosingScope(replacement); - return replacement; - } - return n; - } - - /** - * The ability of a comparison node to be converted to a coercion. - */ - private enum BooleanCoercability { - // Comparison cannot be converted to coercion. - NONE, - // Comparison can be converted to coercion of the left child. - LEFT, - // Comparison can be converted to coercion of the right child. - RIGHT - } - - /** - * Determines whether the types on either side of an (in)equality operation - * are amenable to converting to a simple truthiness check. Specifically, - * this is the case when comparing an object type against null or undefined. - */ - private BooleanCoercability canConvertComparisonToBooleanCoercion( - Node left, Node right, boolean isShallow) { - // Convert null or undefined check of an object to coercion. - boolean leftIsNull = left.isNull(); - boolean rightIsNull = right.isNull(); - boolean leftIsUndefined = NodeUtil.isUndefined(left); - boolean rightIsUndefined = NodeUtil.isUndefined(right); - boolean leftIsNullOrUndefined = leftIsNull || leftIsUndefined; - boolean rightIsNullOrUndefined = rightIsNull || rightIsUndefined; - - boolean leftIsObjectType = isObjectType(left); - boolean rightIsObjectType = isObjectType(right); - if (isShallow) { - // Shallow compare: must guarantee object cannot be the other type of null/undefined. - if ((leftIsObjectType && !left.getTypeI().isNullable() && rightIsUndefined) - || (rightIsObjectType && !right.getTypeI().isNullable() && leftIsUndefined)) { - return leftIsNullOrUndefined ? BooleanCoercability.RIGHT : BooleanCoercability.LEFT; - } - } else { - if ((leftIsObjectType && rightIsNullOrUndefined) - || (rightIsObjectType && leftIsNullOrUndefined)) { - return leftIsNullOrUndefined ? BooleanCoercability.RIGHT : BooleanCoercability.LEFT; - } - } - - return BooleanCoercability.NONE; - } - - /** - * Returns whether the node's type is an object type, which can be - * reduced to a truthiness check when compared against null or undefined. - */ - private static boolean isObjectType(Node n) { - TypeI type = n.getTypeI(); - if (type == null) { - return false; - } - type = type.restrictByNotNullOrUndefined(); - return !type.isUnknownType() - && !type.isBottom() - && !type.isTop() - && type.isObjectType(); - } - - private Node replaceNode(Node original, MeasuredNode measuredNodeReplacement) { if (measuredNodeReplacement.willChange(original)) { Node replacement = measuredNodeReplacement.applyTo(original); diff --git a/src/com/google/javascript/jscomp/PeepholeRemoveDeadCode.java b/src/com/google/javascript/jscomp/PeepholeRemoveDeadCode.java index d03d243613f..3b4ef77e477 100644 --- a/src/com/google/javascript/jscomp/PeepholeRemoveDeadCode.java +++ b/src/com/google/javascript/jscomp/PeepholeRemoveDeadCode.java @@ -395,9 +395,7 @@ private Node tryOptimizeSwitch(Node n) { for (cur = cond.getNext(); cur != null; cur = next) { next = cur.getNext(); caseLabel = cur.getFirstChild(); - // TODO(moz): Use type information if allowed. - caseMatches = PeepholeFoldConstants.evaluateComparison( - Token.SHEQ, cond, caseLabel, false); + caseMatches = PeepholeFoldConstants.evaluateComparison(Token.SHEQ, cond, caseLabel); if (caseMatches == TernaryValue.TRUE) { break; } else if (caseMatches == TernaryValue.UNKNOWN) { diff --git a/src/com/google/javascript/jscomp/PeepholeReplaceKnownMethods.java b/src/com/google/javascript/jscomp/PeepholeReplaceKnownMethods.java index 53dc9d2e72a..415c6c325b9 100644 --- a/src/com/google/javascript/jscomp/PeepholeReplaceKnownMethods.java +++ b/src/com/google/javascript/jscomp/PeepholeReplaceKnownMethods.java @@ -135,10 +135,10 @@ private Node tryFoldKnownStringMethods(Node subtree, Node callTarget) { || (stringNode.getTypeI() != null && stringNode.getTypeI().isStringValueType()))) { if (subtree.hasXChildren(3)) { - Double maybeStart = NodeUtil.getNumberValue(firstArg, useTypes); + Double maybeStart = NodeUtil.getNumberValue(firstArg); if (maybeStart != null) { int start = maybeStart.intValue(); - Double maybeLengthOrEnd = NodeUtil.getNumberValue(firstArg.getNext(), useTypes); + Double maybeLengthOrEnd = NodeUtil.getNumberValue(firstArg.getNext()); if (maybeLengthOrEnd != null) { switch (functionNameString) { case "substr": @@ -540,7 +540,7 @@ private Node tryFoldStringSubstr(Node n, Node stringNode, Node arg1) { int length; String stringAsString = stringNode.getString(); - Double maybeStart = NodeUtil.getNumberValue(arg1, useTypes); + Double maybeStart = NodeUtil.getNumberValue(arg1); if (maybeStart != null) { start = maybeStart.intValue(); } else { @@ -549,7 +549,7 @@ private Node tryFoldStringSubstr(Node n, Node stringNode, Node arg1) { Node arg2 = arg1.getNext(); if (arg2 != null) { - Double maybeLength = NodeUtil.getNumberValue(arg2, useTypes); + Double maybeLength = NodeUtil.getNumberValue(arg2); if (maybeLength != null) { length = maybeLength.intValue(); } else { @@ -596,7 +596,7 @@ private Node tryFoldStringSubstringOrSlice(Node n, Node stringNode, Node arg1) { int end; String stringAsString = stringNode.getString(); - Double maybeStart = NodeUtil.getNumberValue(arg1, useTypes); + Double maybeStart = NodeUtil.getNumberValue(arg1); if (maybeStart != null) { start = maybeStart.intValue(); } else { @@ -605,7 +605,7 @@ private Node tryFoldStringSubstringOrSlice(Node n, Node stringNode, Node arg1) { Node arg2 = arg1.getNext(); if (arg2 != null) { - Double maybeEnd = NodeUtil.getNumberValue(arg2, useTypes); + Double maybeEnd = NodeUtil.getNumberValue(arg2); if (maybeEnd != null) { end = maybeEnd.intValue(); } else { diff --git a/test/com/google/javascript/jscomp/CreateSyntheticBlocksTest.java b/test/com/google/javascript/jscomp/CreateSyntheticBlocksTest.java index 901bde1da5c..54dff61690a 100644 --- a/test/com/google/javascript/jscomp/CreateSyntheticBlocksTest.java +++ b/test/com/google/javascript/jscomp/CreateSyntheticBlocksTest.java @@ -47,8 +47,8 @@ public void process(Node externs, Node js) { compiler, getName(), new PeepholeRemoveDeadCode(), - new PeepholeMinimizeConditions(true /* late */, false /* useTypes */), - new PeepholeFoldConstants(true, false)) + new PeepholeMinimizeConditions(true /* late */), + new PeepholeFoldConstants(true, false /* useTypes */)) .process(externs, js); new MinimizeExitPoints(compiler).asCompilerPass().process(externs, js); new Denormalize(compiler).process(externs, js); diff --git a/test/com/google/javascript/jscomp/MultiPassTest.java b/test/com/google/javascript/jscomp/MultiPassTest.java index f168d6925e1..e7eddf1b6f8 100644 --- a/test/com/google/javascript/jscomp/MultiPassTest.java +++ b/test/com/google/javascript/jscomp/MultiPassTest.java @@ -362,11 +362,11 @@ protected CompilerPass create(AbstractCompiler compiler) { return new PeepholeOptimizationsPass( compiler, getName(), - new PeepholeMinimizeConditions(late, false /* useTypes */), + new PeepholeMinimizeConditions(late), new PeepholeSubstituteAlternateSyntax(late), - new PeepholeReplaceKnownMethods(late, false), + new PeepholeReplaceKnownMethods(late, false /* useTypes */), new PeepholeRemoveDeadCode(), - new PeepholeFoldConstants(late, false), + new PeepholeFoldConstants(late, false /* useTypes */), new PeepholeCollectPropertyAssignments()); } }); diff --git a/test/com/google/javascript/jscomp/PeepholeFoldConstantsTest.java b/test/com/google/javascript/jscomp/PeepholeFoldConstantsTest.java index 245d5bd36f1..21a1e87d853 100644 --- a/test/com/google/javascript/jscomp/PeepholeFoldConstantsTest.java +++ b/test/com/google/javascript/jscomp/PeepholeFoldConstantsTest.java @@ -1361,17 +1361,9 @@ public void testTypeBasedFoldConstant() { test("function f(/** boolean */ x) { x + 1 + 1 + x; }", "function f(/** boolean */ x) { x + 2 + x; }"); - test("function f(/** null */ x) { x + 1 + 1 + x; }", - "function f(/** null */ x) { 2; }"); + testSame("function f(/** null */ x) { var y = true > x; }"); - test("function f(/** undefined */ x) { x + 1 + 1 + x; }", - "function f(/** undefined */ x) { NaN; }"); - - test("function f(/** null */ x) { var y = true > x; }", - "function f(/** null */ x) { var y = true; }"); - - test("function f(/** null */ x) { var y = null > x; }", - "function f(/** null */ x) { var y = false; }"); + testSame("function f(/** null */ x) { var y = null > x; }"); testSame("function f(/** string */ x) { x + 1 + 1 + x; }"); diff --git a/test/com/google/javascript/jscomp/PeepholeIntegrationTest.java b/test/com/google/javascript/jscomp/PeepholeIntegrationTest.java index 47810140cf8..8d39d4ed9c1 100644 --- a/test/com/google/javascript/jscomp/PeepholeIntegrationTest.java +++ b/test/com/google/javascript/jscomp/PeepholeIntegrationTest.java @@ -37,11 +37,11 @@ protected CompilerPass getProcessor(final Compiler compiler) { new PeepholeOptimizationsPass( compiler, getName(), - new PeepholeMinimizeConditions(late, false /* useTypes */), + new PeepholeMinimizeConditions(late), new PeepholeSubstituteAlternateSyntax(late), new PeepholeRemoveDeadCode(), - new PeepholeFoldConstants(late, false), - new PeepholeReplaceKnownMethods(late, false)); + new PeepholeFoldConstants(late, false /* useTypes */), + new PeepholeReplaceKnownMethods(late, false /* useTypes */)); return peepholePass; } diff --git a/test/com/google/javascript/jscomp/PeepholeMinimizeConditionsTest.java b/test/com/google/javascript/jscomp/PeepholeMinimizeConditionsTest.java index 38abb97fad7..ab943b208c7 100644 --- a/test/com/google/javascript/jscomp/PeepholeMinimizeConditionsTest.java +++ b/test/com/google/javascript/jscomp/PeepholeMinimizeConditionsTest.java @@ -24,7 +24,6 @@ public final class PeepholeMinimizeConditionsTest extends TypeICompilerTestCase { private boolean late = true; - private boolean useTypes = true; public PeepholeMinimizeConditionsTest() { super(DEFAULT_EXTERNS); @@ -34,7 +33,6 @@ public PeepholeMinimizeConditionsTest() { protected void setUp() throws Exception { super.setUp(); late = true; - useTypes = true; this.mode = TypeInferenceMode.NEITHER; // NTI warns about property accesses on * ignoreWarnings(DiagnosticGroups.NEW_CHECK_TYPES_EXTRA_CHECKS); @@ -44,7 +42,7 @@ protected void setUp() throws Exception { protected CompilerPass getProcessor(final Compiler compiler) { PeepholeOptimizationsPass peepholePass = new PeepholeOptimizationsPass( - compiler, getName(), new PeepholeMinimizeConditions(late, useTypes)); + compiler, getName(), new PeepholeMinimizeConditions(late)); peepholePass.setRetraverseOnChange(false); return peepholePass; } @@ -772,7 +770,6 @@ public void testIssue925() { public void testCoercionSubstitution_disabled() { this.mode = TypeInferenceMode.BOTH; - useTypes = false; testSame("var x = {}; if (x != null) throw 'a';"); testSame("var x = {}; var y = x != null;"); @@ -782,12 +779,12 @@ public void testCoercionSubstitution_disabled() { public void testCoercionSubstitution_booleanResult0() { this.mode = TypeInferenceMode.BOTH; - test("var x = {}; var y = x != null;", "var x = {}; var y = !!x;"); + testSame("var x = {}; var y = x != null;"); } public void testCoercionSubstitution_booleanResult1() { this.mode = TypeInferenceMode.BOTH; - test("var x = {}; var y = x == null;", "var x = {}; var y = !x;"); + testSame("var x = {}; var y = x == null;"); testSame("var x = {}; var y = x !== null;"); testSame("var x = undefined; var y = x !== null;"); testSame("var x = {}; var y = x === null;"); @@ -801,12 +798,12 @@ public void testCoercionSubstitution_booleanResult1() { public void testCoercionSubstitution_if() { this.mode = TypeInferenceMode.BOTH; - test("var x = {};\nif (x != null) throw 'a';\n", "var x = {};\nif (x) throw 'a';\n"); - test("var x = {};\nif (x == null) throw 'a';\n", "var x = {};\nif (!x) throw 'a';\n"); + test("var x = {};\nif (x != null) throw 'a';\n", "var x={}; if (x!=null) throw 'a'"); + testSame("var x = {};\nif (x == null) throw 'a';\n"); testSame("var x = {};\nif (x !== null) throw 'a';\n"); testSame("var x = {};\nif (x === null) throw 'a';\n"); - test("var x = {};\nif (null != x) throw 'a';\n", "var x = {};\nif (x) throw 'a';\n"); - test("var x = {};\nif (null == x) throw 'a';\n", "var x = {};\nif (!x) throw 'a';\n"); + testSame("var x = {};\nif (null != x) throw 'a';\n"); + testSame("var x = {};\nif (null == x) throw 'a';\n"); testSame("var x = {};\nif (null !== x) throw 'a';\n"); testSame("var x = {};\nif (null === x) throw 'a';\n"); @@ -825,82 +822,34 @@ public void testCoercionSubstitution_if() { public void testCoercionSubstitution_expression() { this.mode = TypeInferenceMode.BOTH; - test( - "var x = {}; x != null && alert('b');", - "var x = {}; x && alert('b');"); + testSame("var x = {}; x != null && alert('b');"); testSame("var x = 1; x != 0 && alert('b');"); } public void testCoercionSubstitution_hook() { this.mode = TypeInferenceMode.BOTH; - test("var x = {};\nvar y = x != null ? 1 : 2;\n", "var x = {};\nvar y = x ? 1 : 2;\n"); - testSame("var x = 1;\nvar y = x != 0 ? 1 : 2;\n"); + testSame( + lines( + "var x = {};", + "var y = x != null ? 1 : 2;")); + testSame( + lines( + "var x = 1;", + "var y = x != 0 ? 1 : 2;")); } public void testCoercionSubstitution_not() { this.mode = TypeInferenceMode.BOTH; - test("var x = {};\nvar y = !(x != null) ? 1 : 2;\n", "var x = {};\nvar y = x ? 2 : 1;\n"); + test( + "var x = {};\nvar y = !(x != null) ? 1 : 2;\n", + "var x = {};\nvar y = (x == null) ? 1 : 2;\n"); test("var x = 1;\nvar y = !(x != 0) ? 1 : 2;\n", "var x = 1;\nvar y = x == 0 ? 1 : 2;\n"); } public void testCoercionSubstitution_while() { this.mode = TypeInferenceMode.BOTH; - test("var x = {};\nwhile (x != null) throw 'a'\n", "var x = {};\nwhile (x) throw 'a';\n"); - testSame("var x = 1;\nwhile (x != 0) throw 'a'\n"); - } - - public void testCoercionSubstitution_nullableType() { - this.mode = TypeInferenceMode.BOTH; - test( - "var x = /** @type {?Object} */ ({}); if (x != null) throw 'a';", - "var x = /** @type {?Object} */ ({}); if (x) throw 'a';"); - // We back off on strict comparison against null. - testSame("var x = /** @type {?Object} */ ({}); if (x !== null) throw 'a';"); - test( - "var x = /** @type {?Object} */ ({}); if (x != undefined) throw 'a';", - "var x = /** @type {?Object} */ ({}); if (x) throw 'a';"); - testSame("var x = /** @type {?Object} */ ({}); if (x !== undefined) throw 'a';"); - test( - "var x = /** @type {!Object|undefined} */ ({}); if (x !== undefined) throw 'a';", - "var x = /** @type {!Object|undefined} */ ({}); if (x) throw 'a';"); - testSame("var x = /** @type {!Object|undefined} */ ({}); if (x !== null) throw 'a';"); - testSame("var x = /** @type {?number} */ (1); if (x != 0) throw 'a';"); - testSame("var x = /** @type {?string} */ (''); if (x != null) throw 'a';"); - testSame("var x = /** @type {?boolean} */ (true); if (x != null) throw 'a';"); - testSame(LINE_JOINER.join( - "/** @enum {string} */", - "var E = { F: '1' };", - "/** @param {?E} x */", - "function f(x) {", - " if (x != null) throw 'a';", - "}")); - testSame(LINE_JOINER.join( - "/** @enum {number} */", - "var E1 = { F: 1 };", - "/** @enum {number} */", - "var E2 = { F: 1 };", - "/** @param {?E1|?E2} x */", - "function f(x) {", - " if (x != null) throw 'a';", - "}")); - test(LINE_JOINER.join( - "/** @enum {Object} */", - "var E = { F: {} };", - "/** @param {?E} x */", - "function f(x) {", - " if (x != null) throw 'a';", - "}"), - LINE_JOINER.join( - "/** @enum {Object} */", - "var E = { F: {} };", - "/** @param {?E} x */", - "function f(x) {", - " if (x) throw 'a';", - "}")); - test( - "if (/** @type {Array|undefined} */ (window['c']) == null) {}", - "if (!/** @type {Array|undefined} */ (window['c'])) {}"); - testSame("if (/** @type {Array|undefined} */ (window['c']) === null) {}"); + testSame("var x = {}; while (x != null) throw 'a';"); + testSame("var x = 1; while (x != 0) throw 'a';"); } public void testCoercionSubstitution_unknownType() { @@ -936,14 +885,8 @@ public void testCoercionSubstitution_boxedNumberVsZero() { public void testCoercionSubstitution_boxedPrimitives() { this.mode = TypeInferenceMode.BOTH; - test( - "var x = new Number();\nif (x != null) throw 'a';\n", - "var x = new Number();\nif (x) throw 'a';\n"); - test( - "var x = new String();\nif (x != null) throw 'a';\n", - "var x = new String();\nif (x) throw 'a';\n"); - test( - "var x = new Boolean();\nif (x != null) throw 'a';\n", - "var x = new Boolean();\nif (x) throw 'a';\n"); + testSame("var x = new Number(); if (x != null) throw 'a';"); + testSame("var x = new String(); if (x != null) throw 'a';"); + testSame("var x = new Boolean();\nif (x != null) throw 'a';"); } }