| /* |
| * 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); |
| } |
| } |