This repository has been archived on 2023-06-18. You can view files and clone it, but cannot push or open issues or pull requests.
ima02/resources/defects4j-checkout-closure-1f/test/com/google/javascript/jscomp/InlineVariablesTest.java

1068 lines
30 KiB
Java
Raw Permalink Normal View History

2023-04-25 11:33:41 +00:00
/*
* Copyright 2008 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;
/**
* Verifies that valid candidates for inlining are inlined, but
* that no dangerous inlining occurs.
*
* @author kushal@google.com (Kushal Dave)
*/
public class InlineVariablesTest extends CompilerTestCase {
private boolean inlineAllStrings = false;
private boolean inlineLocalsOnly = false;
public InlineVariablesTest() {
enableNormalize();
}
@Override
public void setUp() {
super.enableLineNumberCheck(true);
}
@Override
protected CompilerPass getProcessor(final Compiler compiler) {
return new InlineVariables(
compiler,
(inlineLocalsOnly)
? InlineVariables.Mode.LOCALS_ONLY
: InlineVariables.Mode.ALL,
inlineAllStrings);
}
@Override
public void tearDown() {
inlineAllStrings = false;
inlineLocalsOnly = false;
}
// Test respect for scopes and blocks
public void testInlineGlobal() {
test("var x = 1; var z = x;", "var z = 1;");
}
public void testNoInlineExportedName() {
testSame("var _x = 1; var z = _x;");
}
public void testNoInlineExportedName2() {
testSame("var f = function() {}; var _x = f;" +
"var y = function() { _x(); }; var _y = f;");
}
public void testDoNotInlineIncrement() {
testSame("var x = 1; x++;");
}
public void testDoNotInlineDecrement() {
testSame("var x = 1; x--;");
}
public void testDoNotInlineIntoLhsOfAssign() {
testSame("var x = 1; x += 3;");
}
public void testInlineIntoRhsOfAssign() {
test("var x = 1; var y = x;", "var y = 1;");
}
public void testInlineInFunction() {
test("function baz() { var x = 1; var z = x; }",
"function baz() { var z = 1; }");
}
public void testInlineInFunction2() {
test("function baz() { " +
"var a = new obj();"+
"result = a;" +
"}",
"function baz() { " +
"result = new obj()" +
"}");
}
public void testInlineInFunction3() {
testSame(
"function baz() { " +
"var a = new obj();" +
"(function(){a;})();" +
"result = a;" +
"}");
}
public void testInlineInFunction4() {
testSame(
"function baz() { " +
"var a = new obj();" +
"foo.result = a;" +
"}");
}
public void testInlineInFunction5() {
testSame(
"function baz() { " +
"var a = (foo = new obj());" +
"foo.x();" +
"result = a;" +
"}");
}
public void testInlineAcrossModules() {
// TODO(kushal): Make decision about overlap with CrossModuleCodeMotion
test(createModules("var a = 2;", "var b = a;"),
new String[] { "", "var b = 2;" });
}
public void testDoNotExitConditional1() {
testSame("if (true) { var x = 1; } var z = x;");
}
public void testDoNotExitConditional2() {
testSame("if (true) var x = 1; var z = x;");
}
public void testDoNotExitConditional3() {
testSame("var x; if (true) x=1; var z = x;");
}
public void testDoNotExitLoop() {
testSame("while (z) { var x = 3; } var y = x;");
}
public void testDoNotExitForLoop() {
test("for (var i = 1; false; false) var z = i;",
"for (;false;false) var z = 1;");
testSame("for (; false; false) var i = 1; var z = i;");
testSame("for (var i in {}); var z = i;");
}
public void testDoNotEnterSubscope() {
testSame(
"var x = function() {" +
" var self = this; " +
" return function() { var y = self; };" +
"}");
testSame(
"var x = function() {" +
" var y = [1]; " +
" return function() { var z = y; };" +
"}");
}
public void testDoNotExitTry() {
testSame("try { var x = y; } catch (e) {} var z = y; ");
testSame("try { throw e; var x = 1; } catch (e) {} var z = x; ");
}
public void testDoNotEnterCatch() {
testSame("try { } catch (e) { var z = e; } ");
}
public void testDoNotEnterFinally() {
testSame("try { throw e; var x = 1; } catch (e) {} " +
"finally { var z = x; } ");
}
public void testInsideIfConditional() {
test("var a = foo(); if (a) { alert(3); }", "if (foo()) { alert(3); }");
test("var a; a = foo(); if (a) { alert(3); }", "if (foo()) { alert(3); }");
}
public void testOnlyReadAtInitialization() {
test("var a; a = foo();", "foo();");
test("var a; if (a = foo()) { alert(3); }", "if (foo()) { alert(3); }");
test("var a; switch (a = foo()) {}", "switch(foo()) {}");
test("var a; function f(){ return a = foo(); }",
"function f(){ return foo(); }");
test("function f(){ var a; return a = foo(); }",
"function f(){ return foo(); }");
test("var a; with (a = foo()) { alert(3); }", "with (foo()) { alert(3); }");
test("var a; b = (a = foo());", "b = foo();");
test("var a; while(a = foo()) { alert(3); }",
"while(foo()) { alert(3); }");
test("var a; for(;a = foo();) { alert(3); }",
"for(;foo();) { alert(3); }");
test("var a; do {} while(a = foo()) { alert(3); }",
"do {} while(foo()) { alert(3); }");
}
public void testImmutableWithSingleReferenceAfterInitialzation() {
test("var a; a = 1;", "1;");
test("var a; if (a = 1) { alert(3); }", "if (1) { alert(3); }");
test("var a; switch (a = 1) {}", "switch(1) {}");
test("var a; function f(){ return a = 1; }",
"function f(){ return 1; }");
test("function f(){ var a; return a = 1; }",
"function f(){ return 1; }");
test("var a; with (a = 1) { alert(3); }", "with (1) { alert(3); }");
test("var a; b = (a = 1);", "b = 1;");
test("var a; while(a = 1) { alert(3); }",
"while(1) { alert(3); }");
test("var a; for(;a = 1;) { alert(3); }",
"for(;1;) { alert(3); }");
test("var a; do {} while(a = 1) { alert(3); }",
"do {} while(1) { alert(3); }");
}
public void testSingleReferenceAfterInitialzation() {
test("var a; a = foo();a;", "foo();");
testSame("var a; if (a = foo()) { alert(3); } a;");
testSame("var a; switch (a = foo()) {} a;");
testSame("var a; function f(){ return a = foo(); } a;");
testSame("function f(){ var a; return a = foo(); a;}");
testSame("var a; with (a = foo()) { alert(3); } a;");
testSame("var a; b = (a = foo()); a;");
testSame("var a; while(a = foo()) { alert(3); } a;");
testSame("var a; for(;a = foo();) { alert(3); } a;");
testSame("var a; do {} while(a = foo()) { alert(3); } a;");
}
public void testInsideIfBranch() {
testSame("var a = foo(); if (1) { alert(a); }");
}
public void testInsideAndConditional() {
test("var a = foo(); a && alert(3);", "foo() && alert(3);");
}
public void testInsideAndBranch() {
testSame("var a = foo(); 1 && alert(a);");
}
public void testInsideOrBranch() {
testSame("var a = foo(); 1 || alert(a);");
}
public void testInsideHookBranch() {
testSame("var a = foo(); 1 ? alert(a) : alert(3)");
}
public void testInsideHookConditional() {
test("var a = foo(); a ? alert(1) : alert(3)",
"foo() ? alert(1) : alert(3)");
}
public void testInsideOrBranchInsideIfConditional() {
testSame("var a = foo(); if (x || a) {}");
}
public void testInsideOrBranchInsideIfConditionalWithConstant() {
// We don't inline non-immutable constants into branches.
testSame("var a = [false]; if (x || a) {}");
}
public void testCrossFunctionsAsLeftLeaves() {
// Ensures getNext() understands how to walk past a function leaf
test(
new String[] { "var x = function() {};", "",
"function cow() {} var z = x;"},
new String[] { "", "", "function cow() {} var z = function() {};" });
test(
new String[] { "var x = function() {};", "",
"var cow = function() {}; var z = x;"},
new String[] { "", "",
"var cow = function() {}; var z = function() {};" });
testSame(
new String[] { "var x = a;", "",
"(function() { a++; })(); var z = x;"});
test(
new String[] { "var x = a;", "",
"function cow() { a++; }; cow(); var z = x;"},
new String[] { "var x = a;", "",
";(function cow(){ a++; })(); var z = x;"});
testSame(
new String[] { "var x = a;", "",
"cow(); var z = x; function cow() { a++; };"});
}
// Test movement of constant values
public void testDoCrossFunction() {
// We know foo() does not affect x because we require that x is only
// referenced twice.
test("var x = 1; foo(); var z = x;", "foo(); var z = 1;");
}
public void testDoNotCrossReferencingFunction() {
testSame(
"var f = function() { var z = x; };" +
"var x = 1;" +
"f();" +
"var z = x;" +
"f();");
}
// Test tricky declarations and references
public void testChainedAssignment() {
test("var a = 2, b = 2; var c = b;", "var a = 2; var c = 2;");
test("var a = 2, b = 2; var c = a;", "var b = 2; var c = 2;");
test("var a = b = 2; var f = 3; var c = a;", "var f = 3; var c = b = 2;");
testSame("var a = b = 2; var c = b;");
}
public void testForIn() {
testSame("for (var i in j) { var c = i; }");
testSame("var i = 0; for (i in j) ;");
testSame("var i = 0; for (i in j) { var c = i; }");
testSame("i = 0; for (var i in j) { var c = i; }");
testSame("var j = {'key':'value'}; for (var i in j) {print(i)};");
}
// Test movement of values that have (may) side effects
public void testDoCrossNewVariables() {
test("var x = foo(); var z = x;", "var z = foo();");
}
public void testDoNotCrossFunctionCalls() {
testSame("var x = foo(); bar(); var z = x;");
}
// Test movement of values that are complex but lack side effects
public void testDoNotCrossAssignment() {
testSame("var x = {}; var y = x.a; x.a = 1; var z = y;");
testSame("var a = this.id; foo(this.id = 3, a);");
}
public void testDoNotCrossDelete() {
testSame("var x = {}; var y = x.a; delete x.a; var z = y;");
}
public void testDoNotCrossAssignmentPlus() {
testSame("var a = b; b += 2; var c = a;");
}
public void testDoNotCrossIncrement() {
testSame("var a = b.c; b.c++; var d = a;");
}
public void testDoNotCrossConstructor() {
testSame("var a = b; new Foo(); var c = a;");
}
public void testDoCrossVar() {
// Assumes we do not rely on undefined variables (not technically correct!)
test("var a = b; var b = 3; alert(a)", "alert(3);");
}
public void testOverlappingInlines() {
String source =
"a = function(el, x, opt_y) { " +
" var cur = bar(el); " +
" opt_y = x.y; " +
" x = x.x; " +
" var dx = x - cur.x; " +
" var dy = opt_y - cur.y;" +
" foo(el, el.offsetLeft + dx, el.offsetTop + dy); " +
"};";
String expected =
"a = function(el, x, opt_y) { " +
" var cur = bar(el); " +
" opt_y = x.y; " +
" x = x.x; " +
" foo(el, el.offsetLeft + (x - cur.x)," +
" el.offsetTop + (opt_y - cur.y)); " +
"};";
test(source, expected);
}
public void testOverlappingInlineFunctions() {
String source =
"a = function() { " +
" var b = function(args) {var n;}; " +
" var c = function(args) {}; " +
" d(b,c); " +
"};";
String expected =
"a = function() { " +
" d(function(args){var n;}, function(args){}); " +
"};";
test(source, expected);
}
public void testInlineIntoLoops() {
test("var x = true; while (true) alert(x);",
"while (true) alert(true);");
test("var x = true; while (true) for (var i in {}) alert(x);",
"while (true) for (var i in {}) alert(true);");
testSame("var x = [true]; while (true) alert(x);");
}
public void testInlineIntoFunction() {
test("var x = false; var f = function() { alert(x); };",
"var f = function() { alert(false); };");
testSame("var x = [false]; var f = function() { alert(x); };");
}
public void testNoInlineIntoNamedFunction() {
testSame("f(); var x = false; function f() { alert(x); };");
}
public void testInlineIntoNestedNonHoistedNamedFunctions() {
test("f(); var x = false; if (false) function f() { alert(x); };",
"f(); if (false) function f() { alert(false); };");
}
public void testNoInlineIntoNestedNamedFunctions() {
testSame("f(); var x = false; function f() { if (false) { alert(x); } };");
}
public void testNoInlineMutatedVariable() {
testSame("var x = false; if (true) { var y = x; x = true; }");
}
public void testInlineImmutableMultipleTimes() {
test("var x = null; var y = x, z = x;",
"var y = null, z = null;");
test("var x = 3; var y = x, z = x;",
"var y = 3, z = 3;");
}
public void testNoInlineStringMultipleTimesIfNotWorthwhile() {
testSame("var x = 'abcdefghijklmnopqrstuvwxyz'; var y = x, z = x;");
}
public void testInlineStringMultipleTimesWhenAliasingAllStrings() {
inlineAllStrings = true;
test("var x = 'abcdefghijklmnopqrstuvwxyz'; var y = x, z = x;",
"var y = 'abcdefghijklmnopqrstuvwxyz', " +
" z = 'abcdefghijklmnopqrstuvwxyz';");
}
public void testNoInlineBackwards() {
testSame("var y = x; var x = null;");
}
public void testNoInlineOutOfBranch() {
testSame("if (true) var x = null; var y = x;");
}
public void testInterferingInlines() {
test("var a = 3; var f = function() { var x = a; alert(x); };",
"var f = function() { alert(3); };");
}
public void testInlineIntoTryCatch() {
test("var a = true; " +
"try { var b = a; } " +
"catch (e) { var c = a + b; var d = true; } " +
"finally { var f = a + b + c + d; }",
"try { var b = true; } " +
"catch (e) { var c = true + b; var d = true; } " +
"finally { var f = true + b + c + d; }");
}
// Make sure that we still inline constants that are not provably
// written before they're read.
public void testInlineConstants() {
test("function foo() { return XXX; } var XXX = true;",
"function foo() { return true; }");
}
public void testInlineStringWhenWorthwhile() {
test("var x = 'a'; foo(x, x, x);", "foo('a', 'a', 'a');");
}
public void testInlineConstantAlias() {
test("var XXX = new Foo(); q(XXX); var YYY = XXX; bar(YYY)",
"var XXX = new Foo(); q(XXX); bar(XXX)");
}
public void testInlineConstantAliasWithAnnotation() {
test("/** @const */ var xxx = new Foo(); q(xxx); var YYY = xxx; bar(YYY)",
"/** @const */ var xxx = new Foo(); q(xxx); bar(xxx)");
}
public void testInlineConstantAliasWithNonConstant() {
test("var XXX = new Foo(); q(XXX); var y = XXX; bar(y); baz(y)",
"var XXX = new Foo(); q(XXX); bar(XXX); baz(XXX)");
}
public void testCascadingInlines() {
test("var XXX = 4; " +
"function f() { var YYY = XXX; bar(YYY); baz(YYY); }",
"function f() { bar(4); baz(4); }");
}
public void testNoInlineGetpropIntoCall() {
test("var a = b; a();", "b();");
test("var a = b.c; f(a);", "f(b.c);");
testSame("var a = b.c; a();");
}
public void testInlineFunctionDeclaration() {
test("var f = function () {}; var a = f;",
"var a = function () {};");
test("var f = function () {}; foo(); var a = f;",
"foo(); var a = function () {};");
test("var f = function () {}; foo(f);",
"foo(function () {});");
testSame("var f = function () {}; function g() {var a = f;}");
testSame("var f = function () {}; function g() {h(f);}");
}
public void test2388531() {
testSame("var f = function () {};" +
"var g = function () {};" +
"goog.inherits(f, g);");
testSame("var f = function () {};" +
"var g = function () {};" +
"goog$inherits(f, g);");
}
public void testRecursiveFunction1() {
testSame("var x = 0; (function x() { return x ? x() : 3; })();");
}
public void testRecursiveFunction2() {
testSame("function y() { return y(); }");
}
public void testUnreferencedBleedingFunction() {
testSame("var x = function y() {}");
}
public void testReferencedBleedingFunction() {
testSame("var x = function y() { return y(); }");
}
public void testInlineAliases1() {
test("var x = this.foo(); this.bar(); var y = x; this.baz(y);",
"var x = this.foo(); this.bar(); this.baz(x);");
}
public void testInlineAliases1b() {
test("var x = this.foo(); this.bar(); var y; y = x; this.baz(y);",
"var x = this.foo(); this.bar(); x; this.baz(x);");
}
public void testInlineAliases1c() {
test("var x; x = this.foo(); this.bar(); var y = x; this.baz(y);",
"var x; x = this.foo(); this.bar(); this.baz(x);");
}
public void testInlineAliases1d() {
test("var x; x = this.foo(); this.bar(); var y; y = x; this.baz(y);",
"var x; x = this.foo(); this.bar(); x; this.baz(x);");
}
public void testInlineAliases2() {
test("var x = this.foo(); this.bar(); " +
"function f() { var y = x; this.baz(y); }",
"var x = this.foo(); this.bar(); function f() { this.baz(x); }");
}
public void testInlineAliases2b() {
test("var x = this.foo(); this.bar(); " +
"function f() { var y; y = x; this.baz(y); }",
"var x = this.foo(); this.bar(); function f() { this.baz(x); }");
}
public void testInlineAliases2c() {
test("var x; x = this.foo(); this.bar(); " +
"function f() { var y = x; this.baz(y); }",
"var x; x = this.foo(); this.bar(); function f() { this.baz(x); }");
}
public void testInlineAliases2d() {
test("var x; x = this.foo(); this.bar(); " +
"function f() { var y; y = x; this.baz(y); }",
"var x; x = this.foo(); this.bar(); function f() { this.baz(x); }");
}
public void testInlineAliasesInLoop() {
test(
"function f() { " +
" var x = extern();" +
" for (var i = 0; i < 5; i++) {" +
" (function() {" +
" var y = x; window.setTimeout(function() { extern(y); }, 0);" +
" })();" +
" }" +
"}",
"function f() { " +
" var x = extern();" +
" for (var i = 0; i < 5; i++) {" +
" (function() {" +
" window.setTimeout(function() { extern(x); }, 0);" +
" })();" +
" }" +
"}");
}
public void testNoInlineAliasesInLoop() {
testSame(
"function f() { " +
" for (var i = 0; i < 5; i++) {" +
" var x = extern();" +
" (function() {" +
" var y = x; window.setTimeout(function() { extern(y); }, 0);" +
" })();" +
" }" +
"}");
}
public void testNoInlineAliases1() {
testSame(
"var x = this.foo(); this.bar(); var y = x; x = 3; this.baz(y);");
}
public void testNoInlineAliases1b() {
testSame(
"var x = this.foo(); this.bar(); var y; y = x; x = 3; this.baz(y);");
}
public void testNoInlineAliases2() {
testSame(
"var x = this.foo(); this.bar(); var y = x; y = 3; this.baz(y); ");
}
public void testNoInlineAliases2b() {
testSame(
"var x = this.foo(); this.bar(); var y; y = x; y = 3; this.baz(y); ");
}
public void testNoInlineAliases3() {
testSame(
"var x = this.foo(); this.bar(); " +
"function f() { var y = x; g(); this.baz(y); } " +
"function g() { x = 3; }");
}
public void testNoInlineAliases3b() {
testSame(
"var x = this.foo(); this.bar(); " +
"function f() { var y; y = x; g(); this.baz(y); } " +
"function g() { x = 3; }");
}
public void testNoInlineAliases4() {
testSame(
"var x = this.foo(); this.bar(); " +
"function f() { var y = x; y = 3; this.baz(y); }");
}
public void testNoInlineAliases4b() {
testSame(
"var x = this.foo(); this.bar(); " +
"function f() { var y; y = x; y = 3; this.baz(y); }");
}
public void testNoInlineAliases5() {
testSame(
"var x = this.foo(); this.bar(); var y = x; this.bing();" +
"this.baz(y); x = 3;");
}
public void testNoInlineAliases5b() {
testSame(
"var x = this.foo(); this.bar(); var y; y = x; this.bing();" +
"this.baz(y); x = 3;");
}
public void testNoInlineAliases6() {
testSame(
"var x = this.foo(); this.bar(); var y = x; this.bing();" +
"this.baz(y); y = 3;");
}
public void testNoInlineAliases6b() {
testSame(
"var x = this.foo(); this.bar(); var y; y = x; this.bing();" +
"this.baz(y); y = 3;");
}
public void testNoInlineAliases7() {
testSame(
"var x = this.foo(); this.bar(); " +
"function f() { var y = x; this.bing(); this.baz(y); x = 3; }");
}
public void testNoInlineAliases7b() {
testSame(
"var x = this.foo(); this.bar(); " +
"function f() { var y; y = x; this.bing(); this.baz(y); x = 3; }");
}
public void testNoInlineAliases8() {
testSame(
"var x = this.foo(); this.bar(); " +
"function f() { var y = x; this.baz(y); y = 3; }");
}
public void testNoInlineAliases8b() {
testSame(
"var x = this.foo(); this.bar(); " +
"function f() { var y; y = x; this.baz(y); y = 3; }");
}
public void testSideEffectOrder() {
// z can not be changed by the call to y, so x can be inlined.
String EXTERNS = "var z; function f(){}";
test(EXTERNS,
"var x = f(y.a, y); z = x;",
"z = f(y.a, y);", null, null);
// z.b can be changed by the call to y, so x can not be inlined.
testSame(EXTERNS, "var x = f(y.a, y); z.b = x;", null, null);
}
public void testInlineParameterAlias1() {
test(
"function f(x) {" +
" var y = x;" +
" g();" +
" y;y;" +
"}",
"function f(x) {" +
" g();" +
" x;x;" +
"}"
);
}
public void testInlineParameterAlias2() {
test(
"function f(x) {" +
" var y; y = x;" +
" g();" +
" y;y;" +
"}",
"function f(x) {" +
" x;" +
" g();" +
" x;x;" +
"}"
);
}
public void testInlineFunctionAlias1a() {
test(
"function f(x) {}" +
"var y = f;" +
"g();" +
"y();y();",
"var y = function f(x) {};" +
"g();" +
"y();y();"
);
}
public void testInlineFunctionAlias1b() {
test(
"function f(x) {};" +
"f;var y = f;" +
"g();" +
"y();y();",
"function f(x) {};" +
"f;g();" +
"f();f();"
);
}
public void testInlineFunctionAlias2a() {
test(
"function f(x) {}" +
"var y; y = f;" +
"g();" +
"y();y();",
"var y; y = function f(x) {};" +
"g();" +
"y();y();"
);
}
public void testInlineFunctionAlias2b() {
test(
"function f(x) {};" +
"f; var y; y = f;" +
"g();" +
"y();y();",
"function f(x) {};" +
"f; f;" +
"g();" +
"f();f();"
);
}
public void testInlineCatchAlias1() {
test(
"try {" +
"} catch (e) {" +
" var y = e;" +
" g();" +
" y;y;" +
"}",
"try {" +
"} catch (e) {" +
" g();" +
" e;e;" +
"}"
);
}
public void testInlineCatchAlias2() {
test(
"try {" +
"} catch (e) {" +
" var y; y = e;" +
" g();" +
" y;y;" +
"}",
"try {" +
"} catch (e) {" +
" e;" +
" g();" +
" e;e;" +
"}"
);
}
public void testLocalsOnly1() {
inlineLocalsOnly = true;
test(
"var x=1; x; function f() {var x = 1; x;}",
"var x=1; x; function f() {1;}");
}
public void testLocalsOnly2() {
inlineLocalsOnly = true;
test(
"/** @const */\n" +
"var X=1; X;\n" +
"function f() {\n" +
" /** @const */\n" +
" var X = 1; X;\n" +
"}",
"var X=1; X; function f() {1;}");
}
public void testInlineUndefined1() {
test("var x; x;",
"void 0;");
}
public void testInlineUndefined2() {
testSame("var x; x++;");
}
public void testInlineUndefined3() {
testSame("var x; var x;");
}
public void testInlineUndefined4() {
test("var x; x; x;",
"void 0; void 0;");
}
public void testInlineUndefined5() {
test("var x; for(x in a) {}",
"var x; for(x in a) {}");
}
public void testIssue90() {
test("var x; x && alert(1)",
"void 0 && alert(1)");
}
public void testRenamePropertyFunction() {
testSame("var JSCompiler_renameProperty; " +
"JSCompiler_renameProperty('foo')");
}
public void testThisAlias() {
test("function f() { var a = this; a.y(); a.z(); }",
"function f() { this.y(); this.z(); }");
}
public void testThisEscapedAlias() {
testSame(
"function f() { var a = this; var g = function() { a.y(); }; a.z(); }");
}
public void testInlineNamedFunction() {
test("function f() {} f();", "(function f(){})()");
}
public void testIssue378ModifiedArguments1() {
testSame(
"function g(callback) {\n" +
" var f = callback;\n" +
" arguments[0] = this;\n" +
" f.apply(this, arguments);\n" +
"}");
}
public void testIssue378ModifiedArguments2() {
testSame(
"function g(callback) {\n" +
" /** @const */\n" +
" var f = callback;\n" +
" arguments[0] = this;\n" +
" f.apply(this, arguments);\n" +
"}");
}
public void testIssue378EscapedArguments1() {
testSame(
"function g(callback) {\n" +
" var f = callback;\n" +
" h(arguments,this);\n" +
" f.apply(this, arguments);\n" +
"}\n" +
"function h(a,b) {\n" +
" a[0] = b;" +
"}");
}
public void testIssue378EscapedArguments2() {
testSame(
"function g(callback) {\n" +
" /** @const */\n" +
" var f = callback;\n" +
" h(arguments,this);\n" +
" f.apply(this);\n" +
"}\n" +
"function h(a,b) {\n" +
" a[0] = b;" +
"}");
}
public void testIssue378EscapedArguments3() {
test(
"function g(callback) {\n" +
" var f = callback;\n" +
" f.apply(this, arguments);\n" +
"}\n",
"function g(callback) {\n" +
" callback.apply(this, arguments);\n" +
"}\n");
}
public void testIssue378EscapedArguments4() {
testSame(
"function g(callback) {\n" +
" var f = callback;\n" +
" h(arguments[0],this);\n" +
" f.apply(this, arguments);\n" +
"}\n" +
"function h(a,b) {\n" +
" a[0] = b;" +
"}");
}
public void testIssue378ArgumentsRead1() {
test(
"function g(callback) {\n" +
" var f = callback;\n" +
" var g = arguments[0];\n" +
" f.apply(this, arguments);\n" +
"}",
"function g(callback) {\n" +
" var g = arguments[0];\n" +
" callback.apply(this, arguments);\n" +
"}");
}
public void testIssue378ArgumentsRead2() {
test(
"function g(callback) {\n" +
" var f = callback;\n" +
" h(arguments[0],this);\n" +
" f.apply(this, arguments[0]);\n" +
"}\n" +
"function h(a,b) {\n" +
" a[0] = b;" +
"}",
"function g(callback) {\n" +
" h(arguments[0],this);\n" +
" callback.apply(this, arguments[0]);\n" +
"}\n" +
"function h(a,b) {\n" +
" a[0] = b;" +
"}");
}
public void testArgumentsModifiedInOuterFunction() {
test(
"function g(callback) {\n" +
" var f = callback;\n" +
" arguments[0] = this;\n" +
" f.apply(this, arguments);\n" +
" function inner(callback) {" +
" var x = callback;\n" +
" x.apply(this);\n" +
" }" +
"}",
"function g(callback) {\n" +
" var f = callback;\n" +
" arguments[0] = this;\n" +
" f.apply(this, arguments);\n" +
" function inner(callback) {" +
" callback.apply(this);\n" +
" }" +
"}");
}
public void testArgumentsModifiedInInnerFunction() {
test(
"function g(callback) {\n" +
" var f = callback;\n" +
" f.apply(this, arguments);\n" +
" function inner(callback) {" +
" var x = callback;\n" +
" arguments[0] = this;\n" +
" x.apply(this);\n" +
" }" +
"}",
"function g(callback) {\n" +
" callback.apply(this, arguments);\n" +
" function inner(callback) {" +
" var x = callback;\n" +
" arguments[0] = this;\n" +
" x.apply(this);\n" +
" }" +
"}");
}
public void testNoInlineRedeclaredExterns() {
String externs = "var test = 1;";
String code = "/** @suppress {duplicate} */ var test = 2;alert(test);";
test(externs, code, code, null, null);
}
public void testBug6598844() {
testSame(
"function F() { this.a = 0; }" +
"F.prototype.inc = function() { this.a++; return 10; };" +
"F.prototype.bar = function() { var val = inc(); this.a += val; };");
}
}