blob: 3177b093199bb018f895aa51680fc208496b85aa [file] [log] [blame]
/*
* Copyright 2009 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.gwt.dev.js;
/**
* Tests the JsStaticEval optimizer.
*/
public class JsStaticEvalTest extends OptimizerTestBase {
public void testAddLiterals() throws Exception {
assertEquals("alert(42);", optimize("alert(21+21);"));
assertEquals("alert('Hello World');", optimize("alert('Hello '+'World');"));
assertEquals("alert('Hello 42');", optimize("alert('Hello ' + 42);"));
assertEquals("alert('42 Hello');", optimize("alert(42 + ' Hello');"));
assertEquals("alert('42 Hello');", optimize("alert(42.0 + ' Hello');"));
assertEquals("alert('42.2 Hello');", optimize("alert(42.2 + ' Hello');"));
assertEquals("alert('Hello 42.2');", optimize("alert('Hello ' + 42.2);"));
assertEquals("alert('2004318071');", optimize("alert(2004318071 + '');"));
}
public void testAssociativity() throws Exception {
// Simple test
assertEquals("alert(a||b||c||d);", optimize("alert((a||b)||(c||d));"));
assertEquals("alert(a||b||c||d||e||f);", optimize("alert((a||b)||(c||(d||(e||f))));"));
assertEquals("alert(a&&b&&c&&d);", optimize("alert((a&&b)&&(c&&d));"));
// Preserve precedence
assertEquals("alert((a||b)&&(c||d));",
optimize("alert((a || b) && (c || d));"));
assertEquals("alert(a&&b||c&&d);",
optimize("alert((a && b) || ( c && d));"));
assertEquals("a(),b&&c();", optimize("a(), b && c()"));
assertEquals("a()&&b,c();", optimize("a() && b, c()"));
// Don't damage math expressions
assertEquals("alert(seconds/3600);",
optimize("alert(seconds / (60 * 60))"));
assertEquals("alert(seconds/60*60);",
optimize("alert(seconds / 60 * 60)"));
assertEquals("alert(1-(1-foo));", optimize("alert(1 - (1 - foo))"));
// Don't damage assignments
assertEquals("alert((a=0,b=foo));",
optimize("alert((a = 0, b = (bar, foo)))"));
assertEquals("alert(1+(a='2')+3+4);",
optimize("alert(1 + (a = '2') + 3 + 4);"));
assertEquals("alert(1+(a='2')+7);",
optimize("alert(1 + (a = '2') + (3 + 4));"));
// Break comma expressions up
assertEquals("alert((a(),b(),c(),d));",
optimize("alert(((a(),b()),(c(),d)));"));
assertEquals("alert((a(),b(),c(),d));",
optimize("alert(((a(),b()),(c(),d)));"));
// and remove expressions without side effects
assertEquals("alert(d);", optimize("alert(((a,b),(c,d)));"));
// Pattern of coercing a numeric add operation to a string
assertEquals("alert(''+(a+b));", optimize("alert('' + (a + b))"));
// Tests involving numeric and string literals and identifiers
assertEquals("alert(21+(1+$foo));",
optimize("alert((20 + 1) + (1 + $foo));"));
// These are also tricky, because $foo could be non-numeric
assertEquals("alert($foo+1+21);", optimize("alert(($foo + 1) + (20 + 1));"));
assertEquals("alert($bar+13+7+(2+$foo));",
optimize("alert((($bar + (10 + 3)) + (2 + 5)) + (2 + $foo));"));
// Without type info, there's nothing that can be done for this expr
assertEquals("alert($foo+($bar+($baz+$quux)));",
optimize("alert($foo + ($bar + ($baz + $quux)));"));
}
/**
* Test for issue 7088. JsStatic eval infinite loop in
* {@link JsStaticEval.StaticEvalVisitor#endVisit(JsBlock, JsContext)}
*/
public void testDeclareAfterReturn() throws Exception {
// TODO(rluble): Note that the source output has the wrong precedence for function definition
// and application.
assertEquals("(function(){return 0;var a;var b}());",
optimize("(function(){return 0;{var a;var b}})();"));
}
public void testIfWithEmptyThen() throws Exception {
assertEquals("a();", optimize("if (a()) { }"));
}
public void testIfWithEmptyThenAndElseExpression() throws Exception {
assertEquals("a()||b();", optimize("if (a()) { } else { b(); }"));
}
public void testIfWithEmptyThenAndElse() throws Exception {
assertEquals("if(!a()){throw 1}",
optimize("if (a()) { } else { throw 1; }"));
}
public void testIfWithEmptyThenAndEmptyElse() throws Exception {
assertEquals("a();", optimize("if (a()) { } else { }"));
}
public void testIfWithThenAndEmptyElse() throws Exception {
assertEquals("if(a()){throw 1}", optimize("if (a()) { throw 1; } else { }"));
}
public void testIfWithThenExpressionAndEmptyElse() throws Exception {
assertEquals("a()&&b();", optimize("if (a()) { b() } else { }"));
}
public void testIfWithThenExpressionAndElseExpression() throws Exception {
assertEquals("a()?b():c();", optimize("if (a()) { b() } else { c(); }"));
}
public void testIfWithThenExpressionAndElseStatement() throws Exception {
// This can't be optimized further
assertEquals("if(a()){b()}else{throw 1}",
optimize("if (a()) { b() } else { throw 1; }"));
}
public void testLiteralCompares() throws Exception {
assertEquals("alert(false);", optimize("alert(2 != 2)"));
assertEquals("alert(false);", optimize("alert(2 == 3)"));
assertEquals("alert(true);", optimize("alert(2 == 2)"));
assertEquals("alert(true);", optimize("alert(2 != 3)"));
assertEquals("alert(true);", optimize("alert(2 < 3)"));
assertEquals("alert(true);", optimize("alert(3 <= 3)"));
assertEquals("alert(true);", optimize("alert(3 > 2)"));
assertEquals("alert(true);", optimize("alert(3 >= 3)"));
assertEquals("alert(false);", optimize("alert(2 > 3)"));
assertEquals("alert(false);", optimize("alert(2 >= 3)"));
assertEquals("alert(false);", optimize("alert(3 < 2)"));
assertEquals("alert(false);", optimize("alert(3 <= 2)"));
assertEquals("alert(false);", optimize("alert(1.8E+10308 < 1.9E+10308)"));
assertEquals("alert(false);", optimize("alert(1.8E+10308 > 1.9E+10308)"));
assertEquals("alert(true);", optimize("alert(\"a\" == \"a\")"));
assertEquals("alert(true);", optimize("alert(\"a\" === \"a\")"));
assertEquals("alert(true);", optimize("alert(\"a\" != \"b\")"));
assertEquals("alert(true);", optimize("alert(\"a\" !== \"b\")"));
assertEquals("alert(true);", optimize("alert(\"a\" != null)"));
assertEquals("alert(true);", optimize("alert(\"a\" !== null)"));
}
public void testLiteralEqNull() throws Exception {
assertEquals("alert(false);", optimize("alert('test' == null)"));
}
public void testLiteralNeNull() throws Exception {
assertEquals("alert(true);", optimize("alert('test' != null)"));
}
public void testNullEqNull() throws Exception {
assertEquals("alert(true);", optimize("alert(null == null)"));
}
public void testNullNeNull() throws Exception {
assertEquals("alert(false);", optimize("alert(null != null)"));
}
private String optimize(String js) throws Exception {
return optimizeToSource(js, JsStaticEval.class);
}
}