/*
* 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 for {@link AggressiveInlineAliases}. */
public class AggressiveInlineAliasesTest extends CompilerTestCase {
private static final String EXTERNS =
"var window;"
+ "function alert(s) {}"
+ "function parseInt(s) {}"
+ "function String() {};"
+ "var arguments";
public AggressiveInlineAliasesTest() {
super(EXTERNS);
}
@Override
protected int getNumRepetitions() {
return 1;
}
@Override
protected CompilerPass getProcessor(Compiler compiler) {
return new AggressiveInlineAliases(compiler);
}
@Override
public void setUp() {
enableNormalize();
}
public void test_b19179602() {
test(
LINE_JOINER.join(
"var a = {};",
"/** @constructor */ a.b = function() {};",
"a.b.staticProp = 5;",
"/** @constructor */",
"function f() { ",
" while (true) { ",
" var b = a.b;",
" alert(b.staticProp); } }"),
LINE_JOINER.join(
"var a = {};",
"/** @constructor */ a.b = function() {};",
"a.b.staticProp = 5;",
"/** @constructor */",
"function f() {",
" for(; true; ) {",
" var b = a.b;",
" alert(b.staticProp); } }"),
null,
AggressiveInlineAliases.UNSAFE_CTOR_ALIASING);
}
public void test_b19179602_declareOutsideLoop() {
test(
"var a = {};"
+ "a.b = function() {};"
+ "a.b.staticProp = 5;"
+ "function f() { "
+ " var b = a.b;"
+ " while (true) { "
+ " alert(b.staticProp);"
+ " }"
+ "}",
"var a = {};"
+ "a.b = function() {};"
+ "a.b.staticProp = 5;"
+ "function f() {"
+ " var b = null;"
+ " for (;true;)"
+ " alert(a.b.staticProp);"
+ "}");
}
public void testAddPropertyToChildFuncOfUncollapsibleObjectInLocalScope() {
test(
"var a = {};"
+ "a.b = function () {};"
+ "a.b.x = 0;"
+ "var c = a;"
+ "(function() { a.b.y = 1; })();"
+ "a.b.x;"
+ "a.b.y;",
"var a = {};"
+ "a.b = function() {};"
+ "a.b.x = 0;"
+ "var c = null;"
+ "(function() { a.b.y = 1; })();"
+ "a.b.x;"
+ "a.b.y;");
}
public void testAddPropertyToChildOfUncollapsibleCtorInLocalScope() {
test(
"var a = function() {};"
+ "a.b = { x: 0 };"
+ "var c = a;"
+ "(function() { a.b.y = 0; })();"
+ "a.b.y;",
"var a = function() {};"
+ "a.b = { x: 0 };"
+ "var c = null;"
+ "(function() { a.b.y = 0; })();"
+ "a.b.y;");
}
public void testAddPropertyToChildOfUncollapsibleFunctionInLocalScope() {
test(
"function a() {} a.b = { x: 0 };"
+ "var c = a;"
+ "(function() { a.b.y = 0; })();"
+ "a.b.y;",
"function a() {}a.b = { x: 0 };"
+ "var c = null;"
+ "(function() { a.b.y = 0; })();"
+ "a.b.y;");
}
public void testAddPropertyToChildTypeOfUncollapsibleObjectInLocalScope() {
test(
LINE_JOINER.join(
"var a = {};",
"a.b = function () {};",
"a.b.x = 0;",
"var c = a;",
"(function() { a.b.y = 1; })();",
"a.b.x;",
"a.b.y;"),
LINE_JOINER.join(
"var a = {};",
"a.b = function() {};",
"a.b.x = 0;",
"var c = null;",
"(function() { a.b.y = 1; })();",
"a.b.x;",
"a.b.y;"));
}
public void testAddPropertyToUncollapsibleCtorInLocalScopeDepth1() {
test(
"var a = function() {};" + "var c = a;" + "(function() { a.b = 0;" + "})();" + "a.b;",
"var a = function() {};" + "var c = null;" + "(function() { a.b = 0 })();" + "a.b;");
}
public void testAddPropertyToUncollapsibleCtorInLocalScopeDepth2() {
test(
"var a = {};"
+ "a.b = function () {};"
+ "var d = a.b;"
+ "(function() { a.b.c = 0; })();"
+ "a.b.c;",
"var a = {};"
+ "a.b = function() {};"
+ "var d = null;"
+ "(function() { a.b.c = 0; })();"
+ "a.b.c;");
}
public void testAddPropertyToUncollapsibleNamedCtorInLocalScopeDepth1() {
test(
"function a() {} var a$b;" + "var c = a;" + "(function() { a$b = 0;" + "})();" + "a$b;",
"function a() {} var a$b;" + "var c = null;" + "(function() { a$b = 0;" + "})();" + "a$b;");
}
public void testAddPropertyToUncollapsibleObjectInLocalScopeDepth1() {
test(
"var a = {};" + "var c = a;" + "use(c);" + "(function() { a.b = 0;" + "})();" + "a.b;",
"var a = {};" + "var c = null;" + "use(a);" + "(function() { a.b = 0;" + "})();" + "a.b;");
}
public void testAddPropertyToUncollapsibleObjectInLocalScopeDepth2() {
test(
"var a = {};"
+ "a.b = {};"
+ "var d = a.b;"
+ "use(d);"
+ "(function() { a.b.c = 0; })();"
+ "a.b.c;",
"var a = {};"
+ "a.b = {};"
+ "var d = null;"
+ "use(a.b);"
+ "(function() { a.b.c = 0; })();"
+ "a.b.c;");
}
public void testAliasCreatedForClassDepth1_1() {
test(
"var a = {};" + "a.b = function() {};" + "var c = a;" + "c.b = 0;" + "a.b != c.b;",
"var a = {};" + "a.b = function() {};" + "var c = null;" + "a.b = 0;" + "a.b != a.b;");
test(
"var a = {};" + "a.b = function() {};" + "var c = a;" + "c.b = 0;" + "a.b == c.b;",
"var a = {};" + "a.b = function() {};" + "var c = null;" + "a.b = 0;" + "a.b == a.b;");
}
public void testAliasCreatedForCtorDepth1_1() {
test(
"var a = function() {};" + "a.b = 1;" + "var c = a;" + "c.b = 2;" + "a.b == c.b;",
"var a = function() {};" + "a.b = 1;" + "var c = null;" + "a.b = 2;" + "a.b == a.b;");
test(
"var a = function() {};" + "a.b = 1;" + "var c = a;" + "c.b = 2;" + "a.b == c.b;",
"var a = function() {};" + "a.b = 1;" + "var c = null;" + "a.b = 2;" + "a.b == a.b;");
}
public void testAliasCreatedForCtorDepth2() {
test(
"var a = {};" + "a.b = function() {};" + "a.b.c = 1;" + "var d = a.b;" + "a.b.c == d.c;",
"var a = {};" + "a.b = function() {};" + "a.b.c = 1;" + "var d = null;" + "a.b.c == a.b.c");
}
public void testAliasCreatedForFunctionDepth2() {
test(
"var a = {};" + "a.b = function() {};" + "a.b.c = 1;" + "var d = a.b;" + "a.b.c != d.c;",
"var a = {};" + "a.b = function() {};" + "a.b.c = 1;" + "var d = null;" + "a.b.c != a.b.c");
test(
"var a = {};" + "a.b = function() {};" + "a.b.c = 1;" + "var d = a.b;" + "a.b.c == d.c;",
"var a = {};" + "a.b = function() {};" + "a.b.c = 1;" + "var d = null;" + "a.b.c == a.b.c");
}
public void testAliasCreatedForObjectDepth1_1() {
test(
"var a = { b: 0 };" + "var c = a;" + "c.b = 1;" + "a.b == c.b;",
"var a = { b: 0 };" + "var c = null;" + "a.b = 1;" + "a.b == a.b;");
test(
"var a = { b: 0 };" + "var c = a;" + "c.b = 1;" + "a.b == c.b;" + "use(c);",
"var a = { b: 0 };" + "var c = null;" + "a.b = 1;" + "a.b == a.b;" + "use(a);");
}
public void testCodeGeneratedByGoogModule() {
test(
"var $jscomp = {};"
+ "$jscomp.scope = {};"
+ "$jscomp.scope.Foo = function() {};"
+ "var exports = $jscomp.scope.Foo;"
+ "exports.staticprop = { A: 1 };"
+ "var y = exports.staticprop.A;",
"var $jscomp = {};"
+ "$jscomp.scope = {};"
+ "$jscomp.scope.Foo = function() {};"
+ "var exports = null;"
+ "$jscomp.scope.Foo.staticprop = { A: 1 };"
+ "var y = null;");
test(
"var $jscomp = {};"
+ "$jscomp.scope = {};"
+ "$jscomp.scope.Foo = function() {};"
+ "$jscomp.scope.Foo.staticprop = { A: 1 };"
+ "var exports = $jscomp.scope.Foo;"
+ "var y = exports.staticprop.A;",
"var $jscomp = {};"
+ "$jscomp.scope = {};"
+ "$jscomp.scope.Foo = function() {};"
+ "$jscomp.scope.Foo.staticprop = { A: 1 };"
+ "var exports = null;"
+ "var y = null;");
}
public void testCollapse() {
test(
"var a = {};" + "a.b = {};" + "var c = a.b;", "var a = {};" + "a.b = {};" + "var c = null");
test(
"var a = {};" + "a.b = {};" + "var c = a.b;" + "use(c);",
"var a = {};" + "a.b = {};" + "var c = null;" + "use(a.b)");
testSame("var a = {};" + "a.b;");
}
public void testCollapsePropertiesOfClass1() {
test(
LINE_JOINER.join(
"/** @constructor */ var namespace = function() {};",
"goog.inherits(namespace, Object);",
"namespace.includeExtraParam = true;",
"/** @enum { number } */",
"namespace.Param = { param1: 1, param2: 2 };",
"if (namespace.includeExtraParam) namespace.Param.optParam = 3;",
"/** @constructor */",
"function f() { ",
" var Param = namespace.Param;",
" log(namespace.Param.optParam);",
" log(Param.optParam);",
"}"),
LINE_JOINER.join(
"/** @constructor */ var namespace = function() {};",
"goog.inherits(namespace,Object);",
"namespace.includeExtraParam = true;",
"/** @enum { number } */",
"namespace.Param = { param1: 1,param2: 2 };",
"if(namespace.includeExtraParam) namespace.Param.optParam = 3;",
"/** @constructor */",
"function f() {",
" var Param = null;",
" log(namespace.Param.optParam);",
" log(namespace.Param.optParam);",
"}"));
}
public void testCollapsePropertiesOfClass2() {
test(
"var goog = goog || {};"
+ "goog.addSingletonGetter = function(cls) {};"
+ "var a = {};"
+ "a.b = function() {};"
+ "goog.addSingletonGetter(a.b);"
+ "a.b.prototype.get = function(key) {};"
+ "a.b.c = function() {};"
+ "a.b.c.XXX = new a.b.c;"
+ "function f() { "
+ " var x = a.b.getInstance();"
+ " var Key = a.b.c;"
+ " x.get(Key.XXX);"
+ "}",
"var goog = goog || {};"
+ "goog.addSingletonGetter = function(cls) {};"
+ "var a = {};"
+ "a.b = function() {};"
+ "goog.addSingletonGetter(a.b);"
+ "a.b.prototype.get = function(key) {};"
+ "a.b.c = function() {};"
+ "a.b.c.XXX = new a.b.c;"
+ "function f() {"
+ " var x = a.b.getInstance();"
+ " var Key = null;"
+ " x.get(a.b.c.XXX);"
+ "}");
}
public void testCommaOperator() {
test(
"var ns = {};"
+ "ns.Foo = {};"
+ "var Baz = {};"
+ "Baz.Foo = ns.Foo;"
+ "Baz.Foo.bar = 10, 123;",
"var ns = {};"
+ "ns.Foo = {};"
+ "var Baz = {};"
+ "Baz.Foo = null;"
+ "ns.Foo.bar = 10, 123;");
}
public void testDontCrashCtorAliasWithEnum() {
test(
LINE_JOINER.join(
"var ns = {};",
"/** @constructor */ ns.Foo = function () {};",
"var Bar = ns.Foo;",
"/** @const @enum */",
"Bar.prop = { A: 1 };"),
LINE_JOINER.join(
"var ns = {};",
"/** @constructor */ ns.Foo = function() {};",
"var Bar = null;",
"/** @const @enum */",
"ns.Foo.prop = { A: 1 }"));
}
public void testFunctionAlias2() {
test(
"var a = {};" + "a.b = {};" + "a.b.c = function() {};" + "a.b.d = a.b.c;" + "use(a.b.d);",
"var a = {};" + "a.b = {};" + "a.b.c = function() {};" + "a.b.d = null;" + "use(a.b.c);");
}
public void testGlobalAliasOfAncestor() {
test(
"var a = { b: { c: 5 } };" + "function f() { var x = a.b;" + "f(x.c);" + "}",
"var a = { b: { c: 5 } };" + "function f() { var x = null;" + "f(a.b.c);" + "}");
}
public void testGlobalAliasWithProperties1() {
test(
"var ns = {};"
+ "ns.Foo = function() {};"
+ "/** @enum { number } */ ns.Foo.EventType = { A: 1, B: 2 };"
+ "ns.Bar = ns.Foo;"
+ "var x = function() { use(ns.Bar.EventType.A) };"
+ "use(x);",
"var ns = {};"
+ "ns.Foo = function() {};"
+ "/** @enum { number } */ ns.Foo.EventType = { A: 1, B: 2 };"
+ "ns.Bar = null;"
+ "var x = function() { use(ns.Foo.EventType.A) };"
+ "use(x);");
}
public void testGlobalAliasWithProperties2() {
test(
"var ns = {};"
+ "ns.Foo = function() {};"
+ "/** @enum { number } */ ns.Foo.EventType = { A: 1, B: 2 };"
+ "ns.Bar = ns.Foo;"
+ "/** @enum { number } */ ns.Bar.EventType = ns.Foo.EventType;"
+ "var x = function() { use(ns.Bar.EventType.A) };"
+ "use(x)",
"var ns = {};"
+ "ns.Foo = function() {};"
+ "/** @enum { number } */ ns.Foo.EventType = { A: 1, B: 2 };"
+ "ns.Bar = null;"
+ "/** @enum { number } */ ns.Foo.EventType = ns.Foo.EventType;"
+ "var x = function() { use(ns.Foo.EventType.A) };"
+ "use(x)");
}
public void testGlobalAliasWithProperties3() {
test(
"var ns = {};"
+ "ns.Foo = function() {};"
+ "/** @enum { number } */ ns.Foo.EventType = { A: 1, B: 2 };"
+ "ns.Bar = ns.Foo;"
+ "/** @enum { number } */ ns.Bar.Other = { X: 1, Y: 2 };"
+ "var x = function() { use(ns.Bar.Other.X) };"
+ "use(x)",
"var ns = {};"
+ "ns.Foo = function() {};"
+ "/** @enum { number } */ ns.Foo.EventType = { A: 1, B: 2 };"
+ "ns.Bar = null;"
+ "/** @enum { number } */ ns.Foo.Other = { X: 1, Y: 2 };"
+ "var x = function() { use(ns.Foo.Other.X) };"
+ "use(x)");
}
public void testGlobalWriteToNonAncestor() {
test(
"var a = { b: 3 };" + "function f() { var x = a;" + "f(a.b);" + "} a.b = 5;",
"var a = { b: 3 };" + "function f() { var x = null;" + "f(a.b);" + "} a.b = 5;");
}
public void testInlineCtorInObjLit() {
compareJsDoc = true;
test(
LINE_JOINER.join("function Foo() {}", "var Bar = Foo;", "var objlit = { 'prop' : Bar };"),
LINE_JOINER.join("function Foo() {}", "var Bar = null;", "var objlit = { 'prop': Foo };"));
}
public void testLocalAlias1() {
test(
"var a = { b: 3 };" + "function f() { var x = a;" + "f(x.b);" + "}",
"var a = { b: 3 };" + "function f() { var x = null;" + "f(a.b);" + "}");
}
public void testLocalAlias2() {
test(
"var a = { b: 3, c: 4 };" + "function f() { var x = a;" + "f(x.b);" + "f(x.c);" + "}",
"var a = { b: 3, c: 4 };" + "function f() { var x = null;" + "f(a.b);" + "f(a.c);" + "}");
}
public void testLocalAlias3() {
test(
"var a = { b: 3, c: { d: 5 } };"
+ "function f() {"
+ " var x = a;"
+ " f(x.b);"
+ " f(x.c);"
+ " f(x.c.d);"
+ "}",
"var a = { b: 3, c: { d: 5 } };"
+ "function f() {"
+ " var x = null;"
+ " f(a.b);"
+ " f(a.c);"
+ " f(a.c.d)"
+ "}");
}
public void testLocalAlias4() {
test(
"var a = { b: 3 };"
+ "var c = { d: 5 };"
+ "function f() {"
+ " var x = a;"
+ " var y = c;"
+ " f(x.b);"
+ " f(y.d);"
+ "}",
"var a = { b: 3 };"
+ "var c = { d: 5 };"
+ "function f() {"
+ " var x = null;"
+ " var y = null;"
+ " f(a.b);"
+ " f(c.d)"
+ "}");
}
public void testLocalAlias5() {
test(
"var a = { b: { c: 5 } };"
+ "function f() {"
+ " var x = a;"
+ " var y = x.b;"
+ " f(a.b.c);"
+ " f(y.c);"
+ "}",
"var a = { b: { c: 5 } };"
+ "function f() {"
+ " var x = null;"
+ " var y = null;"
+ " f(a.b.c);"
+ " f(a.b.c);"
+ "}");
}
public void testLocalAlias6() {
test(
"var a = { b: 3 };" + "function f() { var x = a;" + "if (x.b) f(x.b);" + "}",
"var a = { b: 3 };" + "function f() { var x = null;" + "if (a.b) f(a.b);" + "}");
}
public void testLocalAlias7() {
test(
"var a = { b: { c: 5 } };" + "function f() { var x = a.b;" + "f(x.c);" + "}",
"var a = { b: { c: 5 } };" + "function f() { var x = null;" + "f(a.b.c);" + "}");
}
public void testLocalAliasOfEnumWithInstanceofCheck() {
test(
LINE_JOINER.join(
"/** @constructor */ var Enums = function() {};",
"/** @enum { number } */",
"Enums.Fruit = { APPLE: 1, BANANA: 2 };",
"/** @constructor */ function foo(f) {",
"if (f instanceof Enums) { alert('what?'); return; }",
"var Fruit = Enums.Fruit;",
"if (f == Fruit.APPLE) alert('apple');",
"if (f == Fruit.BANANA) alert('banana'); }"),
LINE_JOINER.join(
"/** @constructor */ var Enums = function() {};",
"/** @enum { number } */",
"Enums.Fruit = { APPLE: 1,BANANA: 2 };",
"/** @constructor */ function foo(f) {",
"if (f instanceof Enums) { alert('what?'); return; }",
"var Fruit = null;",
"if(f == Enums.Fruit.APPLE) alert('apple');",
"if(f == Enums.Fruit.BANANA) alert('banana'); }"));
}
public void testLocalAliasOfFunction() {
test(
"var a = function() {};" + "a.b = 5;" + "function f() { var x = a.b;" + "f(x);" + "}",
"var a = function() {};" + "a.b = 5;" + "function f() { var x = null;" + "f(a.b);" + "}");
}
public void testLocalWriteToNonAncestor() {
test(
"var a = { b: 3 };" + "function f() { a.b = 5;" + "var x = a;" + "f(a.b);" + "}",
"var a = { b: 3 };" + "function f() { a.b = 5;" + "var x = null;" + "f(a.b);" + "}");
}
public void testMisusedConstructorTag() {
test(
"var a = {};" + "var d = a;" + "a.b = function() {};" + "a.b.c = 0;" + "a.b.c;",
"var a = {};" + "var d = null;" + "a.b = function() {};" + "a.b.c = 0;" + "a.b.c;");
}
public void testNoInlineGetpropIntoCall() {
test(
"var b = x;" + "function f() { var a = b;" + "a();" + "}",
"var b = x;" + "function f() { var a = null;" + "b()" + "}");
}
public void testObjLitAssignmentDepth3() {
test(
"var a = {};" + "a.b = {};" + "a.b.c = { d: 1, e: 2 };" + "var f = a.b.c.d;",
"var a = {};" + "a.b = {};" + "a.b.c = { d: 1,e: 2 };" + "var f = null;");
test(
"var a = {};" + "a.b = {};" + "a.b.c = { d: 1, e: 2 };" + "var f = a.b.c.d;" + "use(f);",
"var a = {};" + "a.b = {};" + "a.b.c = { d: 1,e: 2 };" + "var f = null;" + "use(a.b.c.d);");
test(
"var a = {};"
+ "a.b = {};"
+ "a.b.c = { d: 1, e: 2 };"
+ "var f = a.b.c.d;"
+ "var g = a.b.c.e;",
"var a = {};"
+ "a.b = {};"
+ "a.b.c = { d: 1, e: 2 };"
+ "var f = null;"
+ "var g = null;");
test(
"var a = {};"
+ "a.b = {};"
+ "a.b.c = { d: 1, e: 2 };"
+ "var f = a.b.c.d;"
+ "var g = a.b.c.e;"
+ "use(f, g);",
"var a = {};"
+ "a.b = {};"
+ "a.b.c = { d: 1, e: 2 };"
+ "var f = null;"
+ "var g = null;"
+ "use(a.b.c.d, a.b.c.e);");
testSame(
"var a = {};"
+ "a.b = {};"
+ "a.b.c = { d: 1, e: 2 };"
+ "var f = null;"
+ "var g = null;");
}
public void testObjLitAssignmentDepth4() {
test(
"var a = {};"
+ "a.b = {};"
+ "a.b.c = {};"
+ "a.b.c.d = { e: 1, f: 2 };"
+ "var g = a.b.c.d.e;",
"var a = {};"
+ "a.b = {};"
+ "a.b.c = {};"
+ "a.b.c.d = { e: 1, f: 2 };"
+ "var g = null;");
test(
"var a = {};"
+ "a.b = {};"
+ "a.b.c = {};"
+ "a.b.c.d = { e: 1, f: 2 };"
+ "var g = a.b.c.d.e;"
+ "use(g);",
"var a = {};"
+ "a.b = {};"
+ "a.b.c = {};"
+ "a.b.c.d = { e: 1, f: 2 };"
+ "var g = null;"
+ "use(a.b.c.d.e);");
}
public void testObjLitDeclaration() {
test(
"var a = { b: {}, c: {} };" + "var d = a.b;" + "var e = a.c;",
"var a = { b: {}, c: {} };" + "var d = null;" + "var e = null;");
test(
"var a = { b: {}, c: {} };" + "var d = a.b;" + "var e = a.c;" + "use(d, e);",
"var a = { b: {}, c: {} };" + "var d = null;" + "var e = null;" + "use(a.b,a.c);");
test(
"var a = { b: {}, c: {} };" + "var d = a.b;" + "var e = a.c;",
"var a = { b: {}, c: {} };" + "var d = null;" + "var e = null;");
test(
"var a = { b: {}, c: {} };" + "var d = a.b;" + "var e = a.c;" + "use(d, e);",
"var a = { b: {}, c: {} };" + "var d = null;" + "var e = null;" + "use(a.b, a.c);");
}
public void testObjLitDeclarationUsedInSameVarList() {
test(
"var a = { b: {}, c: {} };" + "var d = a.b;" + "var e = a.c;" + "use(d, e);",
"var a = { b: {}, c: {} };" + "var d = null;" + "var e = null;" + "use(a.b, a.c)");
}
public void testObjLitDeclarationWithGet2() {
test(
"var a = { b: {}, get c() {} };" + "var d = a.b;" + "var e = a.c;",
"var a = { b: {}, get c() {} };" + "var d = null;" + "var e = a.c;");
test(
"var a = { b: {}, get c() {} };" + "var d = a.b;" + "var e = a.c;" + "use(d);",
"var a = { b: {}, get c() {} };" + "var d = null;" + "var e = a.c;" + "use(a.b);");
}
public void testObjLitDeclarationWithSet2() {
test(
"var a = { b: {}, set c(a) {} };" + "var d = a.b;" + "var e = a.c",
"var a = { b: {}, set c(a$jscomp$1) {} };" + "var d = null;" + "var e = a.c;");
test(
"var a = { b: {}, set c(a) {} };" + "var d = a.b;" + "var e = a.c;" + "use(d);",
"var a = { b: {}, set c(a$jscomp$1) {} };"
+ "var d = null;"
+ "var e = a.c;"
+ "use(a.b);");
}
public void testPropertyOfChildFuncOfUncollapsibleObjectDepth1() {
test(
"var a = {};" + "var c = a;" + "a.b = function () {};" + "a.b.x = 0;" + "a.b.x;",
"var a = {};" + "var c = null;" + "a.b = function() {};" + "a.b.x = 0;" + "a.b.x;");
test(
"var a = {};"
+ "var c = a;"
+ "a.b = function () {};"
+ "a.b.x = 0;"
+ "a.b.x;"
+ "use(c);",
"var a = {};"
+ "var c = null;"
+ "a.b = function() {};"
+ "a.b.x = 0;"
+ "a.b.x;"
+ "use(a);");
}
public void testPropertyOfChildFuncOfUncollapsibleObjectDepth2() {
test(
"var a = {};"
+ "a.b = {};"
+ "var c = a.b;"
+ "a.b.c = function () {};"
+ "a.b.c.x = 0;"
+ "a.b.c.x;",
"var a = {};"
+ "a.b = {};"
+ "var c = null;"
+ "a.b.c = function() {};"
+ "a.b.c.x = 0;"
+ "a.b.c.x");
test(
"var a = {};"
+ "a.b = {};"
+ "var c = a.b;"
+ "a.b.c = function () {};"
+ "a.b.c.x = 0;"
+ "a.b.c.x;"
+ "use(c);",
"var a = {};"
+ "a.b = {};"
+ "var c = null;"
+ "a.b.c = function() {};"
+ "a.b.c.x = 0;"
+ "a.b.c.x;"
+ "use(a.b)");
}
public void testTypeDefAlias1() {
test(
"var D = function() {};"
+ "D.L = function() {};"
+ "/** @type { D.L } */ D.L.A = new D.L();"
+ "/** @const */ var M = {};"
+ "/** @typedef { D.L } */ M.L = D.L;"
+ "use(M.L.A);",
"var D = function() {};"
+ "D.L = function() {};"
+ "/** @type { D.L } */ D.L.A = new D.L;"
+ "/** @const */ var M = {};"
+ "/** @typedef { D.L } */ M.L = null;"
+ "use(D.L.A);");
}
}