Merge pull request #9305 from RyanCavanaugh/fix9293

Properly detect circular constructor-declared `this` properties (JS)
This commit is contained in:
Ryan Cavanaugh
2016-06-23 10:30:07 -07:00
committed by GitHub
12 changed files with 66 additions and 67 deletions
+19 -13
View File
@@ -3151,23 +3151,29 @@ namespace ts {
if (declaration.kind === SyntaxKind.ExportAssignment) {
return links.type = checkExpression((<ExportAssignment>declaration).expression);
}
// Handle module.exports = expr
if (declaration.kind === SyntaxKind.BinaryExpression) {
return links.type = getUnionType(map(symbol.declarations, (decl: BinaryExpression) => checkExpressionCached(decl.right)));
}
if (declaration.kind === SyntaxKind.PropertyAccessExpression) {
// Declarations only exist for property access expressions for certain
// special assignment kinds
if (declaration.parent.kind === SyntaxKind.BinaryExpression) {
// Handle exports.p = expr or this.p = expr or className.prototype.method = expr
return links.type = checkExpressionCached((<BinaryExpression>declaration.parent).right);
}
}
// Handle variable, parameter or property
if (!pushTypeResolution(symbol, TypeSystemPropertyName.Type)) {
return unknownType;
}
let type = getWidenedTypeForVariableLikeDeclaration(<VariableLikeDeclaration>declaration, /*reportErrors*/ true);
let type: Type = undefined;
// Handle module.exports = expr or this.p = expr
if (declaration.kind === SyntaxKind.BinaryExpression) {
type = getUnionType(map(symbol.declarations, (decl: BinaryExpression) => checkExpressionCached(decl.right)));
}
else if (declaration.kind === SyntaxKind.PropertyAccessExpression) {
// Declarations only exist for property access expressions for certain
// special assignment kinds
if (declaration.parent.kind === SyntaxKind.BinaryExpression) {
// Handle exports.p = expr or className.prototype.method = expr
type = checkExpressionCached((<BinaryExpression>declaration.parent).right);
}
}
if (type === undefined) {
type = getWidenedTypeForVariableLikeDeclaration(<VariableLikeDeclaration>declaration, /*reportErrors*/ true);
}
if (!popTypeResolution()) {
if ((<VariableLikeDeclaration>symbol.valueDeclaration).type) {
// Variable has type annotation that circularly references the variable itself
@@ -1,9 +0,0 @@
=== tests/cases/compiler/file1.ts ===
c;
>c : Symbol(c, Decl(file2.ts, 0, 5))
=== tests/cases/compiler/file2.ts ===
const c = 0;
>c : Symbol(c, Decl(file2.ts, 0, 5))
@@ -1,10 +0,0 @@
=== tests/cases/compiler/file1.ts ===
c;
>c : number
=== tests/cases/compiler/file2.ts ===
const c = 0;
>c : number
>0 : number
@@ -0,0 +1,17 @@
=== tests/cases/compiler/foo.js ===
export class StackOverflowTest {
>StackOverflowTest : Symbol(StackOverflowTest, Decl(foo.js, 0, 0))
constructor () {
this.testStackOverflow = this.testStackOverflow.bind(this)
>this.testStackOverflow : Symbol(StackOverflowTest.testStackOverflow, Decl(foo.js, 2, 18))
>this : Symbol(StackOverflowTest, Decl(foo.js, 0, 0))
>testStackOverflow : Symbol(StackOverflowTest.testStackOverflow, Decl(foo.js, 2, 18))
>this.testStackOverflow : Symbol(StackOverflowTest.testStackOverflow, Decl(foo.js, 2, 18))
>this : Symbol(StackOverflowTest, Decl(foo.js, 0, 0))
>testStackOverflow : Symbol(StackOverflowTest.testStackOverflow, Decl(foo.js, 2, 18))
>this : Symbol(StackOverflowTest, Decl(foo.js, 0, 0))
}
}
@@ -0,0 +1,21 @@
=== tests/cases/compiler/foo.js ===
export class StackOverflowTest {
>StackOverflowTest : StackOverflowTest
constructor () {
this.testStackOverflow = this.testStackOverflow.bind(this)
>this.testStackOverflow = this.testStackOverflow.bind(this) : any
>this.testStackOverflow : any
>this : this
>testStackOverflow : any
>this.testStackOverflow.bind(this) : any
>this.testStackOverflow.bind : any
>this.testStackOverflow : any
>this : this
>testStackOverflow : any
>bind : any
>this : this
}
}
@@ -1,9 +0,0 @@
=== tests/cases/compiler/file1.ts ===
l;
>l : Symbol(l, Decl(file2.ts, 0, 5))
=== tests/cases/compiler/file2.ts ===
const l = 0;
>l : Symbol(l, Decl(file2.ts, 0, 5))
@@ -1,10 +0,0 @@
=== tests/cases/compiler/file1.ts ===
l;
>l : number
=== tests/cases/compiler/file2.ts ===
const l = 0;
>l : number
>0 : number
@@ -1,6 +0,0 @@
error TS6046: Argument for '--module' option must be: 'none', 'commonjs', 'amd', 'system', 'umd', 'es6', 'es2015'
!!! error TS6046: Argument for '--module' option must be: 'none', 'commonjs', 'amd', 'system', 'umd', 'es6', 'es2015'
==== file.ts (0 errors) ====
@@ -1,2 +0,0 @@
"use strict";
//# sourceMappingURL=file.js.map
@@ -1,6 +0,0 @@
error TS6046: Argument for '--module' option must be: 'none', 'commonjs', 'amd', 'system', 'umd', 'es6', 'es2015'
!!! error TS6046: Argument for '--module' option must be: 'none', 'commonjs', 'amd', 'system', 'umd', 'es6', 'es2015'
==== file.ts (0 errors) ====
@@ -1,2 +0,0 @@
"use strict";
//# sourceMappingURL=file.js.map
@@ -0,0 +1,9 @@
// @allowJs: true
// @noEmit: true
// @filename: foo.js
export class StackOverflowTest {
constructor () {
this.testStackOverflow = this.testStackOverflow.bind(this)
}
}