Allow window. prefix in default-assignment JS decl

This commit is contained in:
Nathan Shively-Sanders
2018-02-09 14:53:34 -08:00
parent 33c084f5df
commit 61ea026b3c
8 changed files with 436 additions and 122 deletions

View File

@@ -18984,6 +18984,9 @@ namespace ts {
}
function checkBinaryExpression(node: BinaryExpression, checkMode?: CheckMode) {
if (node.operatorToken.kind === SyntaxKind.BarBarToken && isInJavaScriptFile(node) && isAssignmentOfDefaultedJavascriptContainerExpression(node.parent)) {
return checkExpression(node.right, checkMode);
}
return checkBinaryLikeExpression(node.left, node.operatorToken, node.right, checkMode, node);
}
@@ -21859,7 +21862,8 @@ namespace ts {
// Node is the primary declaration of the symbol, just validate the initializer
// Don't validate for-in initializer as it is already an error
if (node.initializer && node.parent.parent.kind !== SyntaxKind.ForInStatement) {
checkTypeAssignableTo(checkExpressionCached(node.initializer), type, node, /*headMessage*/ undefined);
const initializer = isInJavaScriptFile(node) && isDeclarationOfDefaultedJavascriptContainerExpression(node) ? (node.initializer as BinaryExpression).right : node.initializer;
checkTypeAssignableTo(checkExpressionCached(initializer), type, node, /*headMessage*/ undefined);
checkParameterInitializer(node);
}
}

View File

@@ -1508,10 +1508,8 @@ namespace ts {
isVariableDeclaration(node) &&
node.initializer &&
isBinaryExpression(node.initializer) &&
// TODO: This will have to change for `var my = window.my || {}`;
isIdentifier(node.initializer.left) &&
isIdentifier(node.name) &&
node.initializer.left.escapedText === node.name.escapedText &&
isSameName(node.name, node.initializer.left as EntityNameExpression) &&
isJavascriptContainerExpression(node.initializer.right);
}
@@ -1534,12 +1532,20 @@ namespace ts {
isJavascriptContainerExpression(node.right.right);
}
function isSameName(left: EntityNameExpression, right: EntityNameExpression): boolean {
if (isIdentifier(left) && isIdentifier(right)) {
return left.escapedText === right.escapedText;
function isSameName(name: EntityNameExpression, initializer: EntityNameExpression): boolean {
if (isIdentifier(name) && isIdentifier(initializer)) {
return name.escapedText === initializer.escapedText;
}
if (isPropertyAccessExpression(left) && isPropertyAccessExpression(right)) {
return left.name.escapedText === right.name.escapedText && isSameName(left.expression, right.expression);
if (isIdentifier(name) && isPropertyAccessExpression(initializer)) {
return (initializer.expression.kind as SyntaxKind.ThisKeyword === SyntaxKind.ThisKeyword ||
isIdentifier(initializer.expression) &&
(initializer.expression.escapedText === "window" as __String ||
initializer.expression.escapedText === "self" as __String ||
initializer.expression.escapedText === "global" as __String)) &&
isSameName(name, initializer.name);
}
if (isPropertyAccessExpression(name) && isPropertyAccessExpression(initializer)) {
return name.name.escapedText === initializer.name.escapedText && isSameName(name.expression, initializer.expression);
}
return false;
}
@@ -1596,7 +1602,7 @@ namespace ts {
return SpecialPropertyAssignmentKind.PrototypeProperty;
}
}
if(isEntityNameExpression(lhs.expression)) {
if (isEntityNameExpression(lhs.expression)) {
return SpecialPropertyAssignmentKind.Property;
}
}

View File

@@ -0,0 +1,75 @@
=== tests/cases/conformance/salsa/a.js ===
var my = my || {};
>my : Symbol(my, Decl(a.js, 0, 3))
>my : Symbol(my, Decl(a.js, 0, 3))
my.app = my.app || {};
>my.app : Symbol(app, Decl(a.js, 0, 18))
>my : Symbol(my, Decl(a.js, 0, 3))
>app : Symbol(app, Decl(a.js, 0, 18))
>my.app : Symbol(app, Decl(a.js, 0, 18))
>my : Symbol(my, Decl(a.js, 0, 3))
>app : Symbol(app, Decl(a.js, 0, 18))
my.app.Application = (function () {
>my.app.Application : Symbol(Application, Decl(a.js, 1, 22))
>my.app : Symbol(app, Decl(a.js, 0, 18))
>my : Symbol(my, Decl(a.js, 0, 3))
>app : Symbol(app, Decl(a.js, 0, 18))
>Application : Symbol(Application, Decl(a.js, 1, 22))
var Application = function () {
>Application : Symbol(Application, Decl(a.js, 4, 3))
//...
};
return Application;
>Application : Symbol(Application, Decl(a.js, 4, 3))
})();
my.app.Application()
>my.app.Application : Symbol(Application, Decl(a.js, 1, 22))
>my.app : Symbol(app, Decl(a.js, 0, 18))
>my : Symbol(my, Decl(a.js, 0, 3))
>app : Symbol(app, Decl(a.js, 0, 18))
>Application : Symbol(Application, Decl(a.js, 1, 22))
=== tests/cases/conformance/salsa/b.js ===
var min = window.min || {};
>min : Symbol(min, Decl(b.js, 0, 3))
>window : Symbol(window, Decl(lib.dom.d.ts, --, --))
min.app = min.app || {};
>min.app : Symbol(app, Decl(b.js, 0, 27))
>min : Symbol(min, Decl(b.js, 0, 3))
>app : Symbol(app, Decl(b.js, 0, 27))
>min.app : Symbol(app, Decl(b.js, 0, 27))
>min : Symbol(min, Decl(b.js, 0, 3))
>app : Symbol(app, Decl(b.js, 0, 27))
min.app.Application = (function () {
>min.app.Application : Symbol(Application, Decl(b.js, 1, 24))
>min.app : Symbol(app, Decl(b.js, 0, 27))
>min : Symbol(min, Decl(b.js, 0, 3))
>app : Symbol(app, Decl(b.js, 0, 27))
>Application : Symbol(Application, Decl(b.js, 1, 24))
var Application = function () {
>Application : Symbol(Application, Decl(b.js, 4, 3))
//...
};
return Application;
>Application : Symbol(Application, Decl(b.js, 4, 3))
})();
min.app.Application()
>min.app.Application : Symbol(Application, Decl(b.js, 1, 24))
>min.app : Symbol(app, Decl(b.js, 0, 27))
>min : Symbol(min, Decl(b.js, 0, 3))
>app : Symbol(app, Decl(b.js, 0, 27))
>Application : Symbol(Application, Decl(b.js, 1, 24))
// TODO: Make sure to include github.com/chadbr/vscodeTestJS
// (though extracted to 4 js files instead of 2 js files and an html)

View File

@@ -0,0 +1,99 @@
=== tests/cases/conformance/salsa/a.js ===
var my = my || {};
>my : { [x: string]: any; app: { [x: string]: any; Application: () => void; }; }
>my || {} : { [x: string]: any; app: { [x: string]: any; Application: () => void; }; }
>my : { [x: string]: any; app: { [x: string]: any; Application: () => void; }; }
>{} : { [x: string]: any; app: { [x: string]: any; Application: () => void; }; }
my.app = my.app || {};
>my.app = my.app || {} : { [x: string]: any; Application: () => void; }
>my.app : { [x: string]: any; Application: () => void; }
>my : { [x: string]: any; app: { [x: string]: any; Application: () => void; }; }
>app : { [x: string]: any; Application: () => void; }
>my.app || {} : { [x: string]: any; Application: () => void; }
>my.app : { [x: string]: any; Application: () => void; }
>my : { [x: string]: any; app: { [x: string]: any; Application: () => void; }; }
>app : { [x: string]: any; Application: () => void; }
>{} : { [x: string]: any; Application: () => void; }
my.app.Application = (function () {
>my.app.Application = (function () {var Application = function () { //...};return Application;})() : () => void
>my.app.Application : () => void
>my.app : { [x: string]: any; Application: () => void; }
>my : { [x: string]: any; app: { [x: string]: any; Application: () => void; }; }
>app : { [x: string]: any; Application: () => void; }
>Application : () => void
>(function () {var Application = function () { //...};return Application;})() : () => void
>(function () {var Application = function () { //...};return Application;}) : () => () => void
>function () {var Application = function () { //...};return Application;} : () => () => void
var Application = function () {
>Application : () => void
>function () { //...} : () => void
//...
};
return Application;
>Application : () => void
})();
my.app.Application()
>my.app.Application() : void
>my.app.Application : () => void
>my.app : { [x: string]: any; Application: () => void; }
>my : { [x: string]: any; app: { [x: string]: any; Application: () => void; }; }
>app : { [x: string]: any; Application: () => void; }
>Application : () => void
=== tests/cases/conformance/salsa/b.js ===
var min = window.min || {};
>min : { [x: string]: any; app: { [x: string]: any; Application: () => void; }; }
>window.min || {} : any
>window.min : any
>window : Window
>min : any
>{} : { [x: string]: any; app: { [x: string]: any; Application: () => void; }; }
min.app = min.app || {};
>min.app = min.app || {} : { [x: string]: any; Application: () => void; }
>min.app : { [x: string]: any; Application: () => void; }
>min : { [x: string]: any; app: { [x: string]: any; Application: () => void; }; }
>app : { [x: string]: any; Application: () => void; }
>min.app || {} : { [x: string]: any; Application: () => void; }
>min.app : { [x: string]: any; Application: () => void; }
>min : { [x: string]: any; app: { [x: string]: any; Application: () => void; }; }
>app : { [x: string]: any; Application: () => void; }
>{} : { [x: string]: any; Application: () => void; }
min.app.Application = (function () {
>min.app.Application = (function () {var Application = function () { //...};return Application;})() : () => void
>min.app.Application : () => void
>min.app : { [x: string]: any; Application: () => void; }
>min : { [x: string]: any; app: { [x: string]: any; Application: () => void; }; }
>app : { [x: string]: any; Application: () => void; }
>Application : () => void
>(function () {var Application = function () { //...};return Application;})() : () => void
>(function () {var Application = function () { //...};return Application;}) : () => () => void
>function () {var Application = function () { //...};return Application;} : () => () => void
var Application = function () {
>Application : () => void
>function () { //...} : () => void
//...
};
return Application;
>Application : () => void
})();
min.app.Application()
>min.app.Application() : void
>min.app.Application : () => void
>min.app : { [x: string]: any; Application: () => void; }
>min : { [x: string]: any; app: { [x: string]: any; Application: () => void; }; }
>app : { [x: string]: any; Application: () => void; }
>Application : () => void
// TODO: Make sure to include github.com/chadbr/vscodeTestJS
// (though extracted to 4 js files instead of 2 js files and an html)

View File

@@ -1,84 +1,113 @@
=== tests/cases/conformance/salsa/a.js ===
// TODO: JSDoc would provide a contextual type, so ... I should test that
// (a number of existing tests fail because of that, I think)
// TODO: Try initializer of function or class I guess (though classes aren't context sensitive)
// TODO: Duplicated declarations should be OK (if they have the same type (??))
var my = my || {};
>my : Symbol(my, Decl(a.js, 4, 3), Decl(a.js, 4, 18))
>my : Symbol(my, Decl(a.js, 4, 3), Decl(a.js, 4, 18))
>my : Symbol(my, Decl(a.js, 1, 3), Decl(a.js, 1, 18))
>my : Symbol(my, Decl(a.js, 1, 3), Decl(a.js, 1, 18))
my.m = function() {
>my.m : Symbol(m, Decl(a.js, 4, 18))
>my : Symbol(my, Decl(a.js, 4, 3), Decl(a.js, 4, 18))
>m : Symbol(m, Decl(a.js, 4, 18))
my.method = function() {
>my.method : Symbol(method, Decl(a.js, 1, 18))
>my : Symbol(my, Decl(a.js, 1, 3), Decl(a.js, 1, 18))
>method : Symbol(method, Decl(a.js, 1, 18))
return 1;
}
my.n = 1;
>my.n : Symbol(n, Decl(a.js, 7, 1))
>my : Symbol(my, Decl(a.js, 4, 3), Decl(a.js, 4, 18))
>n : Symbol(n, Decl(a.js, 7, 1))
my.number = 1;
>my.number : Symbol(number, Decl(a.js, 4, 1))
>my : Symbol(my, Decl(a.js, 1, 3), Decl(a.js, 1, 18))
>number : Symbol(number, Decl(a.js, 4, 1))
my.o = {};
>my.o : Symbol(o, Decl(a.js, 8, 9))
>my : Symbol(my, Decl(a.js, 4, 3), Decl(a.js, 4, 18))
>o : Symbol(o, Decl(a.js, 8, 9))
my.object = {};
>my.object : Symbol(object, Decl(a.js, 5, 14))
>my : Symbol(my, Decl(a.js, 1, 3), Decl(a.js, 1, 18))
>object : Symbol(object, Decl(a.js, 5, 14))
my.predicate = my.predicate || {};
>my.predicate : Symbol(predicate, Decl(a.js, 9, 10), Decl(a.js, 10, 34))
>my : Symbol(my, Decl(a.js, 4, 3), Decl(a.js, 4, 18))
>predicate : Symbol(predicate, Decl(a.js, 9, 10), Decl(a.js, 10, 34))
>my.predicate : Symbol(predicate, Decl(a.js, 9, 10), Decl(a.js, 10, 34))
>my : Symbol(my, Decl(a.js, 4, 3), Decl(a.js, 4, 18))
>predicate : Symbol(predicate, Decl(a.js, 9, 10), Decl(a.js, 10, 34))
>my.predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 7, 34), Decl(a.js, 16, 1))
>my : Symbol(my, Decl(a.js, 1, 3), Decl(a.js, 1, 18))
>predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 7, 34), Decl(a.js, 16, 1))
>my.predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 7, 34), Decl(a.js, 16, 1))
>my : Symbol(my, Decl(a.js, 1, 3), Decl(a.js, 1, 18))
>predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 7, 34), Decl(a.js, 16, 1))
my.predicate.query = function () {
>my.predicate.query : Symbol(query, Decl(a.js, 10, 34))
>my.predicate : Symbol(predicate, Decl(a.js, 9, 10), Decl(a.js, 10, 34))
>my : Symbol(my, Decl(a.js, 4, 3), Decl(a.js, 4, 18))
>predicate : Symbol(predicate, Decl(a.js, 9, 10), Decl(a.js, 10, 34))
>query : Symbol(query, Decl(a.js, 10, 34))
>my.predicate.query : Symbol(query, Decl(a.js, 7, 34))
>my.predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 7, 34), Decl(a.js, 16, 1))
>my : Symbol(my, Decl(a.js, 1, 3), Decl(a.js, 1, 18))
>predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 7, 34), Decl(a.js, 16, 1))
>query : Symbol(query, Decl(a.js, 7, 34))
var me = this;
>me : Symbol(me, Decl(a.js, 12, 7))
>this : Symbol(__object, Decl(a.js, 10, 30))
>me : Symbol(me, Decl(a.js, 9, 7))
>this : Symbol(__object, Decl(a.js, 7, 30))
me.property = false;
>me : Symbol(me, Decl(a.js, 12, 7))
>me : Symbol(me, Decl(a.js, 9, 7))
};
var q = new my.predicate.query();
>q : Symbol(q, Decl(a.js, 15, 3))
>my.predicate.query : Symbol(query, Decl(a.js, 10, 34))
>my.predicate : Symbol(predicate, Decl(a.js, 9, 10), Decl(a.js, 10, 34))
>my : Symbol(my, Decl(a.js, 4, 3), Decl(a.js, 4, 18))
>predicate : Symbol(predicate, Decl(a.js, 9, 10), Decl(a.js, 10, 34))
>query : Symbol(query, Decl(a.js, 10, 34))
>q : Symbol(q, Decl(a.js, 12, 3))
>my.predicate.query : Symbol(query, Decl(a.js, 7, 34))
>my.predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 7, 34), Decl(a.js, 16, 1))
>my : Symbol(my, Decl(a.js, 1, 3), Decl(a.js, 1, 18))
>predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 7, 34), Decl(a.js, 16, 1))
>query : Symbol(query, Decl(a.js, 7, 34))
my.predicate.query.result = 'none'
>my.predicate.query.result : Symbol((Anonymous function).result, Decl(a.js, 15, 33))
>my.predicate.query : Symbol(query, Decl(a.js, 10, 34))
>my.predicate : Symbol(predicate, Decl(a.js, 9, 10), Decl(a.js, 10, 34))
>my : Symbol(my, Decl(a.js, 4, 3), Decl(a.js, 4, 18))
>predicate : Symbol(predicate, Decl(a.js, 9, 10), Decl(a.js, 10, 34))
>query : Symbol(query, Decl(a.js, 10, 34))
>result : Symbol((Anonymous function).result, Decl(a.js, 15, 33))
>my.predicate.query.result : Symbol((Anonymous function).result, Decl(a.js, 12, 33))
>my.predicate.query : Symbol(query, Decl(a.js, 7, 34))
>my.predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 7, 34), Decl(a.js, 16, 1))
>my : Symbol(my, Decl(a.js, 1, 3), Decl(a.js, 1, 18))
>predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 7, 34), Decl(a.js, 16, 1))
>query : Symbol(query, Decl(a.js, 7, 34))
>result : Symbol((Anonymous function).result, Decl(a.js, 12, 33))
my.predicate.sort = my.predicate.sort || function (first, second) {
>my.predicate.sort : Symbol(sort, Decl(a.js, 16, 34))
>my.predicate : Symbol(predicate, Decl(a.js, 9, 10), Decl(a.js, 10, 34))
>my : Symbol(my, Decl(a.js, 4, 3), Decl(a.js, 4, 18))
>predicate : Symbol(predicate, Decl(a.js, 9, 10), Decl(a.js, 10, 34))
>sort : Symbol(sort, Decl(a.js, 16, 34))
>my.predicate.sort : Symbol(sort, Decl(a.js, 16, 34))
>my.predicate : Symbol(predicate, Decl(a.js, 9, 10), Decl(a.js, 10, 34))
>my : Symbol(my, Decl(a.js, 4, 3), Decl(a.js, 4, 18))
>predicate : Symbol(predicate, Decl(a.js, 9, 10), Decl(a.js, 10, 34))
>sort : Symbol(sort, Decl(a.js, 16, 34))
>first : Symbol(first, Decl(a.js, 17, 51))
>second : Symbol(second, Decl(a.js, 17, 57))
>my.predicate.sort : Symbol(sort, Decl(a.js, 13, 34))
>my.predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 7, 34), Decl(a.js, 16, 1))
>my : Symbol(my, Decl(a.js, 1, 3), Decl(a.js, 1, 18))
>predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 7, 34), Decl(a.js, 16, 1))
>sort : Symbol(sort, Decl(a.js, 13, 34))
>my.predicate.sort : Symbol(sort, Decl(a.js, 13, 34))
>my.predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 7, 34), Decl(a.js, 16, 1))
>my : Symbol(my, Decl(a.js, 1, 3), Decl(a.js, 1, 18))
>predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 7, 34), Decl(a.js, 16, 1))
>sort : Symbol(sort, Decl(a.js, 13, 34))
>first : Symbol(first, Decl(a.js, 14, 51))
>second : Symbol(second, Decl(a.js, 14, 57))
return first;
>first : Symbol(first, Decl(a.js, 17, 51))
>first : Symbol(first, Decl(a.js, 14, 51))
}
my.predicate.type = class {
>my.predicate.type : Symbol(type, Decl(a.js, 16, 1))
>my.predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 7, 34), Decl(a.js, 16, 1))
>my : Symbol(my, Decl(a.js, 1, 3), Decl(a.js, 1, 18))
>predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 7, 34), Decl(a.js, 16, 1))
>type : Symbol(type, Decl(a.js, 16, 1))
m() { return 101; }
>m : Symbol((Anonymous class).m, Decl(a.js, 17, 27))
}
// global-ish prefixes
var min = window.min || {};
>min : Symbol(min, Decl(a.js, 23, 3))
min.nest = this.min.nest || function () { };
>min.nest : Symbol(nest, Decl(a.js, 23, 27))
>min : Symbol(min, Decl(a.js, 23, 3))
>nest : Symbol(nest, Decl(a.js, 23, 27))
min.nest.other = self.min.nest.other || class { };
>min.nest.other : Symbol((Anonymous function).other, Decl(a.js, 24, 44))
>min.nest : Symbol(nest, Decl(a.js, 23, 27))
>min : Symbol(min, Decl(a.js, 23, 3))
>nest : Symbol(nest, Decl(a.js, 23, 27))
>other : Symbol((Anonymous function).other, Decl(a.js, 24, 44))
min.property = global.min.property || {};
>min.property : Symbol(property, Decl(a.js, 25, 50))
>min : Symbol(min, Decl(a.js, 23, 3))
>property : Symbol(property, Decl(a.js, 25, 50))

View File

@@ -1,66 +1,63 @@
=== tests/cases/conformance/salsa/a.js ===
// TODO: JSDoc would provide a contextual type, so ... I should test that
// (a number of existing tests fail because of that, I think)
// TODO: Try initializer of function or class I guess (though classes aren't context sensitive)
// TODO: Duplicated declarations should be OK (if they have the same type (??))
var my = my || {};
>my : { [x: string]: any; m: () => number; n: number; o: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; }; }
>my || {} : { [x: string]: any; m: () => number; n: number; o: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; }; }
>my : { [x: string]: any; m: () => number; n: number; o: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; }; }
>{} : { [x: string]: any; m: () => number; n: number; o: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; }; }
>my : { [x: string]: any; method: () => number; number: number; object: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; type: typeof (Anonymous class); }; }
>my || {} : { [x: string]: any; method: () => number; number: number; object: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; type: typeof (Anonymous class); }; }
>my : { [x: string]: any; method: () => number; number: number; object: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; type: typeof (Anonymous class); }; }
>{} : { [x: string]: any; method: () => number; number: number; object: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; type: typeof (Anonymous class); }; }
my.m = function() {
>my.m = function() { return 1;} : () => number
>my.m : () => number
>my : { [x: string]: any; m: () => number; n: number; o: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; }; }
>m : () => number
my.method = function() {
>my.method = function() { return 1;} : () => number
>my.method : () => number
>my : { [x: string]: any; method: () => number; number: number; object: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; type: typeof (Anonymous class); }; }
>method : () => number
>function() { return 1;} : () => number
return 1;
>1 : 1
}
my.n = 1;
>my.n = 1 : 1
>my.n : number
>my : { [x: string]: any; m: () => number; n: number; o: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; }; }
>n : number
my.number = 1;
>my.number = 1 : 1
>my.number : number
>my : { [x: string]: any; method: () => number; number: number; object: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; type: typeof (Anonymous class); }; }
>number : number
>1 : 1
my.o = {};
>my.o = {} : { [x: string]: any; }
>my.o : { [x: string]: any; }
>my : { [x: string]: any; m: () => number; n: number; o: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; }; }
>o : { [x: string]: any; }
my.object = {};
>my.object = {} : { [x: string]: any; }
>my.object : { [x: string]: any; }
>my : { [x: string]: any; method: () => number; number: number; object: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; type: typeof (Anonymous class); }; }
>object : { [x: string]: any; }
>{} : { [x: string]: any; }
my.predicate = my.predicate || {};
>my.predicate = my.predicate || {} : { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; }
>my.predicate : { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; }
>my : { [x: string]: any; m: () => number; n: number; o: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; }; }
>predicate : { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; }
>my.predicate || {} : { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; }
>my.predicate : { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; }
>my : { [x: string]: any; m: () => number; n: number; o: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; }; }
>predicate : { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; }
>{} : { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; }
>my.predicate = my.predicate || {} : { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; type: typeof (Anonymous class); }
>my.predicate : { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; type: typeof (Anonymous class); }
>my : { [x: string]: any; method: () => number; number: number; object: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; type: typeof (Anonymous class); }; }
>predicate : { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; type: typeof (Anonymous class); }
>my.predicate || {} : { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; type: typeof (Anonymous class); }
>my.predicate : { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; type: typeof (Anonymous class); }
>my : { [x: string]: any; method: () => number; number: number; object: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; type: typeof (Anonymous class); }; }
>predicate : { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; type: typeof (Anonymous class); }
>{} : { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; type: typeof (Anonymous class); }
my.predicate.query = function () {
>my.predicate.query = function () { var me = this; me.property = false;} : { (): void; result: string; }
>my.predicate.query : { (): void; result: string; }
>my.predicate : { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; }
>my : { [x: string]: any; m: () => number; n: number; o: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; }; }
>predicate : { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; }
>my.predicate : { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; type: typeof (Anonymous class); }
>my : { [x: string]: any; method: () => number; number: number; object: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; type: typeof (Anonymous class); }; }
>predicate : { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; type: typeof (Anonymous class); }
>query : { (): void; result: string; }
>function () { var me = this; me.property = false;} : { (): void; result: string; }
var me = this;
>me : { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; }
>this : { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; }
>me : { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; type: typeof (Anonymous class); }
>this : { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; type: typeof (Anonymous class); }
me.property = false;
>me.property = false : false
>me.property : any
>me : { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; }
>me : { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; type: typeof (Anonymous class); }
>property : any
>false : false
@@ -69,18 +66,18 @@ var q = new my.predicate.query();
>q : any
>new my.predicate.query() : any
>my.predicate.query : { (): void; result: string; }
>my.predicate : { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; }
>my : { [x: string]: any; m: () => number; n: number; o: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; }; }
>predicate : { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; }
>my.predicate : { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; type: typeof (Anonymous class); }
>my : { [x: string]: any; method: () => number; number: number; object: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; type: typeof (Anonymous class); }; }
>predicate : { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; type: typeof (Anonymous class); }
>query : { (): void; result: string; }
my.predicate.query.result = 'none'
>my.predicate.query.result = 'none' : "none"
>my.predicate.query.result : string
>my.predicate.query : { (): void; result: string; }
>my.predicate : { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; }
>my : { [x: string]: any; m: () => number; n: number; o: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; }; }
>predicate : { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; }
>my.predicate : { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; type: typeof (Anonymous class); }
>my : { [x: string]: any; method: () => number; number: number; object: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; type: typeof (Anonymous class); }; }
>predicate : { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; type: typeof (Anonymous class); }
>query : { (): void; result: string; }
>result : string
>'none' : "none"
@@ -88,15 +85,15 @@ my.predicate.query.result = 'none'
my.predicate.sort = my.predicate.sort || function (first, second) {
>my.predicate.sort = my.predicate.sort || function (first, second) { return first;} : (first: any, second: any) => any
>my.predicate.sort : (first: any, second: any) => any
>my.predicate : { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; }
>my : { [x: string]: any; m: () => number; n: number; o: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; }; }
>predicate : { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; }
>my.predicate : { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; type: typeof (Anonymous class); }
>my : { [x: string]: any; method: () => number; number: number; object: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; type: typeof (Anonymous class); }; }
>predicate : { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; type: typeof (Anonymous class); }
>sort : (first: any, second: any) => any
>my.predicate.sort || function (first, second) { return first;} : (first: any, second: any) => any
>my.predicate.sort : (first: any, second: any) => any
>my.predicate : { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; }
>my : { [x: string]: any; m: () => number; n: number; o: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; }; }
>predicate : { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; }
>my.predicate : { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; type: typeof (Anonymous class); }
>my : { [x: string]: any; method: () => number; number: number; object: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; type: typeof (Anonymous class); }; }
>predicate : { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; type: typeof (Anonymous class); }
>sort : (first: any, second: any) => any
>function (first, second) { return first;} : (first: any, second: any) => any
>first : any
@@ -105,4 +102,70 @@ my.predicate.sort = my.predicate.sort || function (first, second) {
return first;
>first : any
}
my.predicate.type = class {
>my.predicate.type = class { m() { return 101; }} : typeof (Anonymous class)
>my.predicate.type : typeof (Anonymous class)
>my.predicate : { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; type: typeof (Anonymous class); }
>my : { [x: string]: any; method: () => number; number: number; object: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; type: typeof (Anonymous class); }; }
>predicate : { [x: string]: any; query: { (): void; result: string; }; sort: (first: any, second: any) => any; type: typeof (Anonymous class); }
>type : typeof (Anonymous class)
>class { m() { return 101; }} : typeof (Anonymous class)
m() { return 101; }
>m : () => number
>101 : 101
}
// global-ish prefixes
var min = window.min || {};
>min : { [x: string]: any; nest: { (): void; other: typeof (Anonymous class); }; property: { [x: string]: any; }; }
>window.min || {} : any
>window.min : any
>window : any
>min : any
>{} : { [x: string]: any; nest: { (): void; other: typeof (Anonymous class); }; property: { [x: string]: any; }; }
min.nest = this.min.nest || function () { };
>min.nest = this.min.nest || function () { } : { (): void; other: typeof (Anonymous class); }
>min.nest : { (): void; other: typeof (Anonymous class); }
>min : { [x: string]: any; nest: { (): void; other: typeof (Anonymous class); }; property: { [x: string]: any; }; }
>nest : { (): void; other: typeof (Anonymous class); }
>this.min.nest || function () { } : { (): void; other: typeof (Anonymous class); }
>this.min.nest : any
>this.min : any
>this : any
>min : any
>nest : any
>function () { } : { (): void; other: typeof (Anonymous class); }
min.nest.other = self.min.nest.other || class { };
>min.nest.other = self.min.nest.other || class { } : typeof (Anonymous class)
>min.nest.other : typeof (Anonymous class)
>min.nest : { (): void; other: typeof (Anonymous class); }
>min : { [x: string]: any; nest: { (): void; other: typeof (Anonymous class); }; property: { [x: string]: any; }; }
>nest : { (): void; other: typeof (Anonymous class); }
>other : typeof (Anonymous class)
>self.min.nest.other || class { } : typeof (Anonymous class)
>self.min.nest.other : any
>self.min.nest : any
>self.min : any
>self : any
>min : any
>nest : any
>other : any
>class { } : typeof (Anonymous class)
min.property = global.min.property || {};
>min.property = global.min.property || {} : { [x: string]: any; }
>min.property : { [x: string]: any; }
>min : { [x: string]: any; nest: { (): void; other: typeof (Anonymous class); }; property: { [x: string]: any; }; }
>property : { [x: string]: any; }
>global.min.property || {} : { [x: string]: any; }
>global.min.property : any
>global.min : any
>global : any
>min : any
>property : any
>{} : { [x: string]: any; }

View File

@@ -0,0 +1,31 @@
// @noEmit: true
// @allowJs: true
// @checkJs: true
// @target: es6
// @lib: es6,dom
// @Filename: a.js
var my = my || {};
my.app = my.app || {};
my.app.Application = (function () {
var Application = function () {
//...
};
return Application;
})();
my.app.Application()
// @Filename: b.js
var min = window.min || {};
min.app = min.app || {};
min.app.Application = (function () {
var Application = function () {
//...
};
return Application;
})();
min.app.Application()
// TODO: Make sure to include github.com/chadbr/vscodeTestJS
// (though extracted to 4 js files instead of 2 js files and an html)

View File

@@ -5,15 +5,12 @@
// @Filename: a.js
// TODO: JSDoc would provide a contextual type, so ... I should test that
// (a number of existing tests fail because of that, I think)
// TODO: Try initializer of function or class I guess (though classes aren't context sensitive)
// TODO: Duplicated declarations should be OK (if they have the same type (??))
var my = my || {};
my.m = function() {
my.method = function() {
return 1;
}
my.n = 1;
my.o = {};
my.number = 1;
my.object = {};
my.predicate = my.predicate || {};
my.predicate.query = function () {
var me = this;
@@ -24,3 +21,13 @@ my.predicate.query.result = 'none'
my.predicate.sort = my.predicate.sort || function (first, second) {
return first;
}
my.predicate.type = class {
m() { return 101; }
}
// global-ish prefixes
var min = window.min || {};
min.nest = this.min.nest || function () { };
min.nest.other = self.min.nest.other || class { };
min.property = global.min.property || {};