/*
* 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;
import com.google.common.collect.Lists;
import com.google.javascript.jscomp.CompilerOptions.LanguageMode;
import java.util.List;
public class J2clPropertyInlinerPassTest extends CompilerTestCase {
public J2clPropertyInlinerPassTest() {
this.enableNormalize(); // Inlining will fail if normailization hasn't happened yet.
setAcceptedLanguage(LanguageMode.ECMASCRIPT6_TYPED);
}
@Override
protected CompilerPass getProcessor(Compiler compiler) {
return new J2clPropertyInlinerPass(compiler);
}
@Override
protected CompilerOptions getOptions() {
CompilerOptions options = super.getOptions();
options.setJ2clPass(CompilerOptions.J2clPassMode.ON);
return options;
}
@Override
protected int getNumRepetitions() {
return 1;
}
private void testDoesntChange(List<SourceFile> js) {
test(js, js);
}
public void testNoInlineNonJ2clProps() {
testDoesntChange(
Lists.newArrayList(
SourceFile.fromCode(
"someFile.js",
"var A = function() {};"
+ "var A$$0clinit = function() {"
+ " A$$0x = 2;"
+ "};"
+ "Object.defineProperties(A, {x :{"
+ " configurable:true,"
+ " enumerable:true,"
+ " get:function() {"
+ " return A$$0clinit(), A$$0x;"
+ " }"
+ "}});"
+ "var A$$0x = null;"
+ "var x = A.x;")));
}
public void testNoInlineNonJ2clPropsValue() {
testDoesntChange(
Lists.newArrayList(
SourceFile.fromCode(
"someFile.js",
"var A = function() {};"
+ "var A$$0clinit = function() {"
+ " A$$0x = 2;"
+ "};"
+ "Object.defineProperties(A, {x :{"
+ " configurable:true,"
+ " enumerable:true,"
+ " value: 2"
+ "}});"
+ "var A$$0x = null;"
+ "var x = A.x;")));
}
// In this test we want to remove the J2CL property but not the entire Object.defineProperties
// since it also defines another non J2CL property.
public void testNoStripDefineProperties() {
test(
Lists.newArrayList(
SourceFile.fromCode(
"someFile.js",
LINE_JOINER.join(
"var A = function() {};",
"A.$clinit = function() {",
" A.$j2cl_prop = 2;",
"};",
"Object.defineProperties(A, {",
" j2cl_prop: {",
" configurable: true,",
" enumerable: true,",
" get: function() {",
" return A.$clinit(), A.$j2cl_prop;",
" },",
" set: function(value) {",
" A.$clinit(), A.$j2cl_prop = value;",
" }",
" },",
" non_j2cl_prop: {",
" configurable: true,",
" enumerable: true,",
" get: function() {",
" return 55;",
" },",
" set: function(v) {",
" console.log(v);",
" }",
" },",
"});"))),
Lists.newArrayList(
SourceFile.fromCode(
"someFile.js",
LINE_JOINER.join(
"var A = function() {};",
"A.$clinit = function() {",
" A.$j2cl_prop = 2;",
"};",
"Object.defineProperties(A, {",
" non_j2cl_prop: {",
" configurable: true,",
" enumerable: true,",
" get: function() {",
" return 55;",
" },",
" set: function(v) {",
" console.log(v);",
" }",
" },",
"});"))));
}
public void testInlineDefinePropertiesGetter() {
test(
Lists.newArrayList(
SourceFile.fromCode(
"someFile.js",
LINE_JOINER.join(
"var A = function() {};",
"A.$clinit = function() {",
" A.$x = 2;",
"};",
"Object.defineProperties(A, {x: {",
" configurable:true,",
" enumerable:true,",
" get:function() {",
" return A.$clinit(), A.$x;",
" },",
" set: function(value) {",
" A.$clinit(), A.$x = value;",
" }",
"}});",
"A.$x = 3;",
"var xx = A.x;"))),
Lists.newArrayList(
SourceFile.fromCode(
"someFile.js",
LINE_JOINER.join(
"var A = function() {};",
"A.$clinit = function() {",
" A.$x = 2;",
"};",
"A.$x = 3;",
"var xx = (A.$clinit(), A.$x);"))));
}
public void testInlineDefinePropertiesSetter() {
test(
Lists.newArrayList(
SourceFile.fromCode(
"someFile.js",
LINE_JOINER.join(
"var A = function() {};",
"A.$clinit = function() {",
" A.$x = 2;",
"};",
"Object.defineProperties(A, {x: {",
" configurable:true,",
" enumerable:true,",
" get:function() {",
" return A.$clinit(), A.$x;",
" },",
" set: function(value) {",
" A.$clinit(), A.$x = value;",
" }",
"}});",
"A.$x = 3;",
"A.x = 10;"))),
Lists.newArrayList(
SourceFile.fromCode(
"someFile.js",
LINE_JOINER.join(
"var A = function() {};",
"A.$clinit = function() {",
" A.$x = 2;",
"};",
"A.$x = 3;",
"{(A.$clinit(), A.$x = 10);}"))));
}
public void testInlineGettersInQualifier() {
test(
Lists.newArrayList(
SourceFile.fromCode(
"someFile.js",
LINE_JOINER.join(
"var A = function() {};",
"A.$clinit = function() {",
" A.$x = {y: 2};",
"};",
"Object.defineProperties(A, {x: {",
" configurable:true,",
" enumerable:true,",
" get:function() {",
" return A.$clinit(), A.$x;",
" },",
" set: function(value) {",
" A.$clinit(), A.$x = value;",
" }",
"}});",
"A.$x = null;",
"var xy = A.x.y;"))),
Lists.newArrayList(
SourceFile.fromCode(
"someFile.js",
LINE_JOINER.join(
"var A = function() {};",
"A.$clinit = function() {",
" A.$x = {y: 2};",
"};",
"A.$x = null;",
"var xy = (A.$clinit(), A.$x).y;"))));
}
public void testNoInlineCompoundAssignment() {
testDoesntChange(
Lists.newArrayList(
SourceFile.fromCode(
"someFile.js",
LINE_JOINER.join(
"var A = function() {};",
"A.$clinit = function() {",
" A.$x = 2;",
"};",
"Object.defineProperties(A, {x: {",
" configurable:true,",
" enumerable:true,",
" get:function() {",
" return A.$clinit(), A.$x;",
" },",
" set: function(value) {",
" A.$clinit(), A.$x = value;",
" }",
"}});",
"A.$x = 3;",
"A.x += 5;"))));
}
public void testNoInlineIncrementGetter() {
// Test ++
testDoesntChange(
Lists.newArrayList(
SourceFile.fromCode(
"someFile.js",
LINE_JOINER.join(
"var A = function() {};",
"A.$clinit = function() {",
" A.$x = 2;",
"};",
"Object.defineProperties(A, {x: {",
" configurable:true,",
" enumerable:true,",
" get:function() {",
" return A.$clinit(), A.$x;",
" },",
" set: function(value) {",
" A.$clinit(), A.$x = value;",
" }",
"}});",
"A.$x = 3;",
"A.x--;"))));
// Test --
testDoesntChange(
Lists.newArrayList(
SourceFile.fromCode(
"someFile.js",
LINE_JOINER.join(
"var A = function() {};",
"A.$clinit = function() {",
" A.$x = 2;",
"};",
"Object.defineProperties(A, {x: {",
" configurable:true,",
" enumerable:true,",
" get:function() {",
" return A.$clinit(), A.$x;",
" },",
" set: function(value) {",
" A.$clinit(), A.$x = value;",
" }",
"}});",
"A.$x = 3;",
"A.x++;"))));
}
}