/* * Copyright 2009 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; /** * Tests for {@link FunctionRewriter} * */ public class FunctionRewriterTest extends CompilerTestCase { private static final String RETURNARG_HELPER = "function JSCompiler_returnArg(JSCompiler_returnArg_value){" + " return function() { return JSCompiler_returnArg_value }" + "}"; private static final String GET_HELPER = "function JSCompiler_get(JSCompiler_get_name){" + " return function() { return this[JSCompiler_get_name] }" + "}"; private static final String SET_HELPER = "function JSCompiler_set(JSCompiler_set_name) {" + " return function(JSCompiler_set_value){" + " this[JSCompiler_set_name]=JSCompiler_set_value" + " }" + "}"; private static final String EMPTY_HELPER = "function JSCompiler_emptyFn() {" + " return function(){}" + "}"; private static final String IDENTITY_HELPER = "function JSCompiler_identityFn() {" + " return function(JSCompiler_identityFn_value) {" + " return JSCompiler_identityFn_value" + " }" + "}"; @Override protected void setUp() { super.enableLineNumberCheck(false); } @Override protected FunctionRewriter getProcessor(Compiler compiler) { return new FunctionRewriter(compiler); } @Override protected int getNumRepetitions() { // Pass reaches steady state after just 1 iteration return 1; } public void testReplaceReturnConst1() { String source = "a.prototype.foo = function() {return \"foobar\"}"; checkCompilesToSame(source, 3); checkCompilesTo(source, RETURNARG_HELPER, "a.prototype.foo = JSCompiler_returnArg(\"foobar\")", 4); } public void testReplaceReturnConst2() { checkCompilesToSame("a.prototype.foo = function() {return foobar}", 10); } public void testReplaceReturnConst3() { String source = "a.prototype.foo = function() {return void 0;}"; checkCompilesToSame(source, 3); checkCompilesTo(source, RETURNARG_HELPER, "a.prototype.foo = JSCompiler_returnArg(void 0)", 4); } public void testReplaceGetter1() { String source = "a.prototype.foo = function() {return this.foo_}"; checkCompilesToSame(source, 3); checkCompilesTo(source, GET_HELPER, "a.prototype.foo = JSCompiler_get(\"foo_\")", 4); } public void testReplaceGetter2() { checkCompilesToSame("a.prototype.foo = function() {return}", 10); } public void testReplaceSetter1() { String source = "a.prototype.foo = function(v) {this.foo_ = v}"; checkCompilesToSame(source, 4); checkCompilesTo(source, SET_HELPER, "a.prototype.foo = JSCompiler_set(\"foo_\")", 5); } public void testReplaceSetter2() { String source = "a.prototype.foo = function(v, v2) {this.foo_ = v}"; checkCompilesToSame(source, 3); checkCompilesTo(source, SET_HELPER, "a.prototype.foo = JSCompiler_set(\"foo_\")", 4); } public void testReplaceSetter3() { checkCompilesToSame("a.prototype.foo = function() {this.foo_ = v}", 10); } public void testReplaceSetter4() { checkCompilesToSame( "a.prototype.foo = function(v, v2) {this.foo_ = v2}", 10); } public void testReplaceEmptyFunction1() { String source = "a.prototype.foo = function() {}"; checkCompilesToSame(source, 4); checkCompilesTo(source, EMPTY_HELPER, "a.prototype.foo = JSCompiler_emptyFn()", 5); } public void testReplaceEmptyFunction2() { checkCompilesToSame("function foo() {}", 10); } public void testReplaceEmptyFunction3() { String source = "var foo = function() {}"; checkCompilesToSame(source, 4); checkCompilesTo(source, EMPTY_HELPER, "var foo = JSCompiler_emptyFn()", 5); } public void testReplaceIdentityFunction1() { String source = "a.prototype.foo = function(a) {return a}"; checkCompilesToSame(source, 2); checkCompilesTo(source, IDENTITY_HELPER, "a.prototype.foo = JSCompiler_identityFn()", 3); } public void testReplaceIdentityFunction2() { checkCompilesToSame("a.prototype.foo = function(a) {return a + 1}", 10); } public void testIssue538() { checkCompilesToSame( "/** @constructor */\n" + "WebInspector.Setting = function() {}\n" + "WebInspector.Setting.prototype = {\n" + " get name0(){return this._name;},\n" + " get name1(){return this._name;},\n" + " get name2(){return this._name;},\n" + " get name3(){return this._name;},\n" + " get name4(){return this._name;},\n" + " get name5(){return this._name;},\n" + " get name6(){return this._name;},\n" + " get name7(){return this._name;},\n" + " get name8(){return this._name;},\n" + " get name9(){return this._name;},\n" + "}", 1); } private void checkCompilesTo(String src, String expectedHdr, String expectedBody, int repetitions) { StringBuilder srcBuffer = new StringBuilder(); StringBuilder expectedBuffer = new StringBuilder(); expectedBuffer.append(expectedHdr); for (int idx = 0; idx < repetitions; idx++) { if (idx != 0) { srcBuffer.append(";"); expectedBuffer.append(";"); } srcBuffer.append(src); expectedBuffer.append(expectedBody); } test(srcBuffer.toString(), expectedBuffer.toString()); } private void checkCompilesToSame(String src, int repetitions) { checkCompilesTo(src, "", src, repetitions); } }