/*
* Copyright 2014 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.javascript.jscomp.CompilerOptions.LanguageMode;
public final class DeclaredGlobalExternsOnWindowTest extends Es6CompilerTestCase {
@Override
protected CompilerPass getProcessor(Compiler compiler) {
return new DeclaredGlobalExternsOnWindow(compiler);
}
@Override
protected void setUp() {
allowExternsChanges(true);
enableTypeCheck();
runTypeCheckAfterProcessing = true;
}
@Override
protected int getNumRepetitions() {
return 1;
}
public void testWindowProperty1a() {
testExternChanges("var window; var a;", "", "var window;var a;window.a");
}
// No "var window;" so this is a no-op.
public void testWindowProperty1b() {
testExternChanges("var a", "", "var a");
}
public void testWindowProperty2() {
testExternChanges("", "var a", "");
}
public void testWindowProperty3a() {
testExternChanges("var window; function f() {}", "var b",
"var window;function f(){}window.f;");
}
// No "var window;" so this is a no-op.
public void testWindowProperty3b() {
testExternChanges("function f() {}", "var b", "function f(){}");
}
public void testWindowProperty4() {
testExternChanges("", "function f() {}", "");
}
public void testWindowProperty5a() {
testExternChanges("var window; var x = function f() {}", "var b",
"var window;var x=function f(){};window.x;");
testExternChanges("var window; var x = function () {}", "var b",
"var window;var x=function(){};window.x;");
}
// No "var window;" so this is a no-op.
public void testWindowProperty5b() {
testExternChanges("var x = function f() {}", "var b", "var x=function f(){}");
}
public void testWindowProperty5c() {
testExternChanges(
"var window; var x = ()=>{}",
"var b",
"var window;var x=()=>{};window.x;",
LanguageMode.ECMASCRIPT_2015);
}
public void testWindowProperty6() {
testExternChanges("var window; /** @const {number} */ var n;", "",
LINE_JOINER.join(
"var window;",
"/** @const {number} */ var n;",
"/** @const {number} @suppress {const,duplicate} */ window.n;"));
}
public void testWindowProperty7() {
testExternChanges("var window; /** @const */ var ns = {}", "",
LINE_JOINER.join(
"var window;",
"/** @const */ var ns = {};",
"/** @suppress {const,duplicate} @const */ window.ns = ns;"));
}
public void testNamespaceAliasing() {
testExternChanges(
LINE_JOINER.join(
"var window;",
"/** @const */",
"var ns = {};",
"/** @const */",
"var ns2 = ns;"),
"",
LINE_JOINER.join(
"var window;",
"/** @const */",
"var ns = {};",
"/** @const */",
"var ns2 = ns;",
"/** @suppress {const,duplicate} @const */",
"window.ns = ns;",
"/** @suppress {const,duplicate} @const */",
"window.ns2 = ns;"));
}
public void testWindowProperty8() {
testExternChanges("var window; /** @constructor */ function Foo() {}", "",
LINE_JOINER.join(
"var window;",
"/** @constructor */ function Foo(){}",
"/** @constructor @suppress {const,duplicate} */ window.Foo = Foo;"));
}
public void testEnumWindowProperty() {
testExternChanges("var window; /** @enum {string} */ var Enum = { A: 'str' };", "",
LINE_JOINER.join(
"var window;",
"/** @enum {string} */ var Enum = { A: 'str' };",
"/** @enum {string} @suppress {const,duplicate} */ window.Enum = Enum;"));
}
/**
* Test to make sure the compiler knows the type of "window.x"
* is the same as that of "x".
*/
public void testWindowPropertyWithJsDoc() {
testSame(
"var window;\n/** @type {string} */ var x;",
LINE_JOINER.join(
"/** @param {number} n*/",
"function f(n) {}",
"f(window.x);"),
TypeValidator.TYPE_MISMATCH_WARNING);
}
public void testEnum() {
testSame(
"/** @enum {string} */ var Enum = {FOO: 'foo', BAR: 'bar'};",
LINE_JOINER.join(
"/** @param {Enum} e*/",
"function f(e) {}",
"f(window.Enum.FOO);"),
null);
}
/**
* Test to make sure that if Foo is a constructor, Foo is considered
* to be the same type as window.Foo.
*/
public void testConstructorIsSameType() {
testSame(
"var window;\n/** @constructor */ function Foo() {}\n",
LINE_JOINER.join(
"/** @param {!window.Foo} f*/",
"function bar(f) {}",
"bar(new Foo());"),
null);
testSame(
"/** @constructor */ function Foo() {}\n",
LINE_JOINER.join(
"/** @param {!Foo} f*/",
"function bar(f) {}",
"bar(new window.Foo());"),
null);
}
}