/*
* Copyright 2016 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;
public class J2clConstantHoisterPassTest extends CompilerTestCase {
@Override
protected CompilerPass getProcessor(final Compiler compiler) {
return new J2clConstantHoisterPass(compiler);
}
@Override
protected CompilerOptions getOptions() {
CompilerOptions options = super.getOptions();
options.setJ2clPass(CompilerOptions.J2clPassMode.ON);
return options;
}
public void testHoistClinitConstantAssignments() {
test(
LINE_JOINER.join(
"var someClass = /** @constructor */ function() {};",
"someClass.$clinit = function() {",
" someClass.$clinit = function() {};",
" someClass$foo = true;",
" someClass$bar = 'hey';",
" someClass$buzz = function() { return someClass$bar; };",
"};",
"var someClass$foo = false;",
"var someClass$bar = null;",
"var someClass$buzz = null;"),
LINE_JOINER.join(
"var someClass = /** @constructor */ function() {};",
"someClass.$clinit = function() {",
" someClass.$clinit = function() {};",
"};",
"var someClass$foo = true;",
"var someClass$bar = 'hey';",
"var someClass$buzz = function(){ return someClass$bar; };"));
}
public void testHoistClinitConstantAssignments_avoidUnsafe() {
testSame(
LINE_JOINER.join(
"var someClass = /** @constructor */ function() {};",
"someClass.$clinit = function() {",
" someClass.$clinit = function() {};",
" someClass$foo1 = true;", // More than two assignments.
" someClass$foo2 = true;", // More than two assignments.
" someClass$bar = true;", // Also initialized by another method.
" someClass$zoo = true;", // Not initialized in declaration phase.
" someClass$hoo = someClass$zoo;", // Not literal value.
"};",
"someClass.$otherMethod = function() {",
" someClass$foo1 |= true;", // Compound assignment to make it less trivial to detect.
" someClass$foo2++;", // Compound assignment to make it less trivial to detect.
" someClass$bar = true;",
"};",
"var someClass$foo1 = false;",
"var someClass$foo2 = false;",
"var someClass$hoo = false;"));
}
/**
* Tests that hoisting works as expected when encountering a clinit that has been devirtualized.
*/
public void testHoistClinitConstantAssignments_devirtualized() {
test(
LINE_JOINER.join(
"var someClass = /** @constructor */ function() {};",
"var someClass$$0clinit = function() {",
" someClass$$0clinit = function() {};",
" someClass$shouldHoist = true;",
" someClass$shouldNotHoist = new Object();",
"};",
"var someClass$shouldHoist = false;",
"var someClass$shouldNotHoist = null;"),
LINE_JOINER.join(
"var someClass = /** @constructor */ function() {};",
"var someClass$$0clinit = function() {",
" someClass$$0clinit = function() {};",
" someClass$shouldNotHoist = new Object();",
"};",
"var someClass$shouldHoist = true;",
"var someClass$shouldNotHoist = null;"));
}
public void testHoistClinitConstantAssignments_avoidUnsafeFunc() {
testSame(
LINE_JOINER.join(
"var someClass = /** @constructor */ function() {};",
"someClass.$clinit = function() {",
" someClass.$clinit = function() {};",
" var x = 10;",
" someClass$foo = function() { return x; };", // Depends on the scope of the clinit.
"};",
"var someClass$foo = null;"));
testSame(
LINE_JOINER.join(
"var someClass = /** @constructor */ function() {};",
"someClass.$clinit = function() {",
" someClass.$clinit = function() {};",
" var x = 10;",
" someClass$foo = function() { return 1; };", // x is assumed to be used
"};",
"var someClass$foo = null;"));
}
}