Don't crash on property access with type (#25170)

* Don't crash on property access with type

* Move test
This commit is contained in:
Andy
2018-06-25 11:25:52 -07:00
committed by GitHub
parent b3a6428186
commit e8e80d2bbd
6 changed files with 62 additions and 9 deletions
+4 -4
View File
@@ -4650,15 +4650,15 @@ namespace ts {
let jsDocType: Type | undefined;
for (const declaration of symbol.declarations) {
let declarationInConstructor = false;
const expression = declaration.kind === SyntaxKind.BinaryExpression ? <BinaryExpression>declaration :
declaration.kind === SyntaxKind.PropertyAccessExpression ? cast(declaration.parent, isBinaryExpression) :
const expression = isBinaryExpression(declaration) ? declaration :
isPropertyAccessExpression(declaration) ? isBinaryExpression(declaration.parent) ? declaration.parent : declaration :
undefined;
if (!expression) {
return errorType;
}
const special = getSpecialPropertyAssignmentKind(expression);
const special = isPropertyAccessExpression(expression) ? getSpecialPropertyAccessKind(expression) : getSpecialPropertyAssignmentKind(expression);
if (special === SpecialPropertyAssignmentKind.ThisProperty) {
const thisContainer = getThisContainer(expression, /*includeArrowFunctions*/ false);
// Properties defined in a constructor (or base constructor, or javascript constructor function) don't get undefined added.
@@ -4687,7 +4687,7 @@ namespace ts {
errorNextVariableOrPropertyDeclarationMustHaveSameType(jsDocType, declaration, declarationType);
}
}
else if (!jsDocType) {
else if (!jsDocType && isBinaryExpression(expression)) {
// If we don't have an explicit JSDoc type, get the type from the expression.
let type = getWidenedLiteralType(checkExpressionCached(expression.right));
+9 -5
View File
@@ -1887,6 +1887,14 @@ namespace ts {
return SpecialPropertyAssignmentKind.None;
}
const lhs = expr.left;
if (isEntityNameExpression(lhs.expression) && lhs.name.escapedText === "prototype" && isObjectLiteralExpression(getInitializerOfBinaryExpression(expr))) {
// F.prototype = { ... }
return SpecialPropertyAssignmentKind.Prototype;
}
return getSpecialPropertyAccessKind(lhs);
}
export function getSpecialPropertyAccessKind(lhs: PropertyAccessExpression): SpecialPropertyAssignmentKind {
if (lhs.expression.kind === SyntaxKind.ThisKeyword) {
return SpecialPropertyAssignmentKind.ThisProperty;
}
@@ -1895,11 +1903,7 @@ namespace ts {
return SpecialPropertyAssignmentKind.ModuleExports;
}
else if (isEntityNameExpression(lhs.expression)) {
if (lhs.name.escapedText === "prototype" && isObjectLiteralExpression(getInitializerOfBinaryExpression(expr))) {
// F.prototype = { ... }
return SpecialPropertyAssignmentKind.Prototype;
}
else if (isPrototypeAccess(lhs.expression)) {
if (isPrototypeAccess(lhs.expression)) {
// F.G....prototype.x = expr
return SpecialPropertyAssignmentKind.PrototypeProperty;
}
+1
View File
@@ -6262,6 +6262,7 @@ declare namespace ts {
function isExportsIdentifier(node: Node): boolean;
function isModuleExportsPropertyAccessExpression(node: Node): boolean;
function getSpecialPropertyAssignmentKind(expr: BinaryExpression): SpecialPropertyAssignmentKind;
function getSpecialPropertyAccessKind(lhs: PropertyAccessExpression): SpecialPropertyAssignmentKind;
function getInitializerOfBinaryExpression(expr: BinaryExpression): Expression;
function isPrototypePropertyAssignment(node: Node): boolean;
function isSpecialPropertyDeclaration(expr: PropertyAccessExpression): boolean;
@@ -0,0 +1,16 @@
=== /a.js ===
function C() { this.x = false; };
>C : Symbol(C, Decl(a.js, 0, 0))
>x : Symbol(C.x, Decl(a.js, 0, 14), Decl(a.js, 0, 33))
/** @type {number} */
C.prototype.x;
>C.prototype : Symbol(Function.prototype, Decl(lib.es5.d.ts, --, --))
>C : Symbol(C, Decl(a.js, 0, 0))
>prototype : Symbol(Function.prototype, Decl(lib.es5.d.ts, --, --))
new C().x;
>new C().x : Symbol(C.x, Decl(a.js, 0, 14), Decl(a.js, 0, 33))
>C : Symbol(C, Decl(a.js, 0, 0))
>x : Symbol(C.x, Decl(a.js, 0, 14), Decl(a.js, 0, 33))
@@ -0,0 +1,23 @@
=== /a.js ===
function C() { this.x = false; };
>C : typeof C
>this.x = false : false
>this.x : any
>this : any
>x : any
>false : false
/** @type {number} */
C.prototype.x;
>C.prototype.x : any
>C.prototype : any
>C : typeof C
>prototype : any
>x : any
new C().x;
>new C().x : number
>new C() : C
>C : typeof C
>x : number
@@ -0,0 +1,9 @@
// @allowJs: true
// @checkJs: true
// @noEmit: true
// @Filename: /a.js
function C() { this.x = false; };
/** @type {number} */
C.prototype.x;
new C().x;