/* * Copyright 2017 The Closure Compiler Authors. * * 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.javascript.jscomp; import com.google.javascript.jscomp.CompilerOptions.LanguageMode; /** * Tests for {@link HoistVarsOutOfBlocks} */ public final class HoistVarsOutOfBlocksTest extends CompilerTestCase { @Override protected CompilerPass getProcessor(final Compiler compiler) { return new HoistVarsOutOfBlocks(compiler); } @Override public CompilerOptions getOptions(CompilerOptions options) { options.setLanguage(LanguageMode.ECMASCRIPT_NEXT); return options; } public void testHoist() { test( "alert(x); if (cond) { var x = 1; }", "var x; alert(x); if (cond) { x = 1; }"); } public void testHoistMultipleVariables() { test( "alert(x); if (cond) { var x = 1, y = 2; }", "var x; alert(x); if (cond) { x = 1; var y = 2; }"); test( "alert(x + y); if (cond) { var x = 1, y = 2; }", "var y; var x; alert(x + y); if (cond) { x = 1; y = 2; }"); test( "alert(y); if (cond) { var x = 1, y = 2, z = 3; }", "var y; alert(y); if (cond) { var x = 1; y = 2; var z = 3; }"); } public void testNoHoist() { testSame("if (cond) { var x = 1; alert(x); }"); } public void testDontHoistFromForLoop() { testSame( LINE_JOINER.join( "for (var i = 0; i < 10; i++) {", " alert(i);", "}", "", "i = 0;")); testSame( LINE_JOINER.join( "for (var i = 0, j = 0; i < 10; i++) {", " alert(i);", "}", "", "i = 0;")); } public void testDontHoistFromForInLoop() { testSame( LINE_JOINER.join( "for (var i in arr) {", " alert(arr[i]);", "}", "", "i = 0;")); } public void testDontHoistFromForOfLoop() { testSame( LINE_JOINER.join( "for (var x of arr) {", " alert(x);", "}", "", "x = 0;")); } public void testDeclInCatchBlock() { test( LINE_JOINER.join( "try {", " x;", "} catch (e) {", " var x;", "}"), LINE_JOINER.join( "var x;", "try {", " x;", "} catch (e) {", "}")); } public void testVarReferencedInHoistedFunction() { test( LINE_JOINER.join( "(function() {", " {", " var x = 0;", " }", " function f2() {", " alert(x);", " }", " f2();", "})();"), LINE_JOINER.join( "(function() {", " var x;", " {", " x = 0;", " }", " function f2() {", " alert(x);", " }", " f2();", "})();")); } public void testDestructuring() { testSame( LINE_JOINER.join( "(function(y) {", " {", " var {x} = y;", " }", " alert(x);", "})();")); } public void testDontHoistEntireVarStatement() { test( LINE_JOINER.join( "if (false) {", " var x, y = sideEffect();", "}", "alert(x);"), LINE_JOINER.join( "var x;", "if (false) {", " var y = sideEffect();", "}", "alert(x);")); } // Similar to the code in Codemirror 2 that caused a crash in an earlier version of this pass. public void testDontCrashDuplicateHoistedVar() { test( LINE_JOINER.join( "function f() {", " if (true) {", " for (var i = 0; i < 10; i++) {", " var x = 0;", " alert(x);", " }", " } else {", " var unused = 0, i = 0, x;", " }", "}"), LINE_JOINER.join( "function f() {", " var x;", " var i;", " var x;", " if (true) {", " for (var i = 0; i < 10; i++) {", " x = 0;", " alert(x);", " }", " } else {", " var unused = 0;", " i = 0;", " }", "}")); } }