/*
* 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;
/**
* Tests that the property renaming primitive goog.reflect.objectProperty
* is recognized across the optimization passes.
*
* @author chadkillingsworth@gmail.com (Chad Killingsworth)
*/
public final class ClosurePrimitivesIntegrationTest extends IntegrationTestCase {
private static final String RENAME_FN_DEFINITION = LINE_JOINER.join(
"/** @const */ var goog = {};",
"/** @const */ goog.reflect = {};",
"/**",
" * @param {string} propName",
" * @param {Object} type",
" * @return {string}",
" */",
"goog.reflect.objectProperty = function(propName, type) {",
" return propName;",
"};"
);
private static final String EXTERNS = LINE_JOINER.join(
"/**",
" * @fileoverview",
" * @externs",
" */",
"/** @constructor */ function Console() {}",
"/** @param {*} input */ Console.prototype.log = function(input) {};",
"/** @type {Console} */ var console;");
private boolean useSimpleMode = false;
public void testPrototypePropRename() {
test(createCompilerOptions(),
new String[] {
EXTERNS,
RENAME_FN_DEFINITION,
LINE_JOINER.join(
"/** @constructor */ function Foo() {}",
"window['Foo'] = Foo;",
"Foo.prototype.log = function(input) { console.log(input) };",
"Foo.prototype['log'] = Foo.prototype.log;",
"var foo = new Foo;",
"console.log(goog.reflect.objectProperty('log', foo));",
"foo.log('foobar');")},
new String[] {
"",
"",
LINE_JOINER.join(
"function a() {}",
"window.Foo = a;",
"a.prototype.a = function(b) { console.log(b) };",
"a.prototype.log = a.prototype.a;",
"var c = new a;",
"console.log('a');",
"c.a('foobar');")}
);
}
public void testPrototypePropRenameSimple() {
useSimpleMode = true;
test(
createCompilerOptions(),
new String[] {
EXTERNS,
RENAME_FN_DEFINITION,
LINE_JOINER.join(
"/** @constructor */ function Foo() {}",
"window['Foo'] = Foo;",
"Foo.prototype.log = function(input) { console.log(input) };",
"Foo.prototype['log'] = Foo.prototype.log;",
"var foo = new Foo;",
"console.log(goog.reflect.objectProperty('log', foo));",
"foo.log('foobar');")
},
new String[] {
"",
LINE_JOINER.join(
"var goog= { reflect: {} };",
"goog.reflect.objectProperty = function(a,b) { return a; };"),
LINE_JOINER.join(
"function Foo() {}",
"window.Foo = Foo;",
"Foo.prototype.log = function(a) { console.log(a); };",
"Foo.prototype.log = Foo.prototype.log;",
"var foo = new Foo;",
"console.log('log');",
"foo.log('foobar');")
});
}
public void testStaticPropRename() {
test(createCompilerOptions(),
LINE_JOINER.join(
RENAME_FN_DEFINITION,
"/** @const */ var foo = {};",
"foo.log = function(input) { alert(input) };",
"alert(goog.reflect.objectProperty('log', foo));",
"foo.log('foobar');"),
LINE_JOINER.join(
"var b = { a: function(a) { alert(a); } };",
"alert('a');",
"b.a('foobar');"));
}
public void testStaticPropRenameSimple() {
useSimpleMode = true;
test(
createCompilerOptions(),
LINE_JOINER.join(
RENAME_FN_DEFINITION,
"/** @const */ var foo = {};",
"foo.log = function(input) { alert(input) };",
"alert(goog.reflect.objectProperty('log', foo));",
"foo.log('foobar');"),
LINE_JOINER.join(
"var goog= { reflect: {} };",
"goog.reflect.objectProperty = function(a,b) { return a; };",
"var foo = {",
" log: function(a) { alert(a) }",
"};",
"alert('log');",
"foo.log('foobar');"));
}
@Override
protected CompilerOptions createCompilerOptions() {
CompilerOptions options = new CompilerOptions();
if (useSimpleMode) {
CompilationLevel.SIMPLE_OPTIMIZATIONS.setOptionsForCompilationLevel(options);
} else {
CompilationLevel.ADVANCED_OPTIMIZATIONS.setOptionsForCompilationLevel(options);
CompilationLevel.ADVANCED_OPTIMIZATIONS.setTypeBasedOptimizationOptions(options);
}
options.setCodingConvention(new ClosureCodingConvention());
WarningLevel.VERBOSE.setOptionsForWarningLevel(options);
return options;
}
}