From dbaf1f67567b58063173af7b34cb6e2fb13d7d47 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 22 Feb 2017 14:16:20 -0800 Subject: [PATCH] isConstructorType checks base constraint for undefined Previously, it assumed there was always a base constraint, which is true for correct code. For incorrect code, the base constraint may be missing, which caused a crash because the base constraint was undefined. --- src/compiler/checker.ts | 2 +- .../baseConstraintOfDecorator.errors.txt | 23 +++++++++++ .../reference/baseConstraintOfDecorator.js | 40 +++++++++++++++++++ .../compiler/baseConstraintOfDecorator.ts | 8 ++++ 4 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/baseConstraintOfDecorator.errors.txt create mode 100644 tests/baselines/reference/baseConstraintOfDecorator.js create mode 100644 tests/cases/compiler/baseConstraintOfDecorator.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 5fe3a0de1a5..83fea11c993 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3952,7 +3952,7 @@ namespace ts { } if (type.flags & TypeFlags.TypeVariable) { const constraint = getBaseConstraintOfType(type); - return isValidBaseType(constraint) && isMixinConstructorType(constraint); + return constraint && isValidBaseType(constraint) && isMixinConstructorType(constraint); } return false; } diff --git a/tests/baselines/reference/baseConstraintOfDecorator.errors.txt b/tests/baselines/reference/baseConstraintOfDecorator.errors.txt new file mode 100644 index 00000000000..efc0c59f9ee --- /dev/null +++ b/tests/baselines/reference/baseConstraintOfDecorator.errors.txt @@ -0,0 +1,23 @@ +tests/cases/compiler/baseConstraintOfDecorator.ts(2,5): error TS2322: Type 'typeof decoratorFunc' is not assignable to type 'TFunction'. +tests/cases/compiler/baseConstraintOfDecorator.ts(2,40): error TS2507: Type 'TFunction' is not a constructor function type. + + +==== tests/cases/compiler/baseConstraintOfDecorator.ts (2 errors) ==== + export function classExtender(superClass: TFunction, _instanceModifier: (instance: any, args: any[]) => void): TFunction { + return class decoratorFunc extends superClass { + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ~~~~~~~~~~ +!!! error TS2507: Type 'TFunction' is not a constructor function type. + constructor(...args: any[]) { + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + super(...args); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + _instanceModifier(this, args); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + } + ~~~~~~~~~ + }; + ~~~~~~ +!!! error TS2322: Type 'typeof decoratorFunc' is not assignable to type 'TFunction'. + } + \ No newline at end of file diff --git a/tests/baselines/reference/baseConstraintOfDecorator.js b/tests/baselines/reference/baseConstraintOfDecorator.js new file mode 100644 index 00000000000..0bceaca2509 --- /dev/null +++ b/tests/baselines/reference/baseConstraintOfDecorator.js @@ -0,0 +1,40 @@ +//// [baseConstraintOfDecorator.ts] +export function classExtender(superClass: TFunction, _instanceModifier: (instance: any, args: any[]) => void): TFunction { + return class decoratorFunc extends superClass { + constructor(...args: any[]) { + super(...args); + _instanceModifier(this, args); + } + }; +} + + +//// [baseConstraintOfDecorator.js] +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +exports.__esModule = true; +function classExtender(superClass, _instanceModifier) { + return (function (_super) { + __extends(decoratorFunc, _super); + function decoratorFunc() { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + var _this = _super.apply(this, args) || this; + _instanceModifier(_this, args); + return _this; + } + return decoratorFunc; + }(superClass)); +} +exports.classExtender = classExtender; diff --git a/tests/cases/compiler/baseConstraintOfDecorator.ts b/tests/cases/compiler/baseConstraintOfDecorator.ts new file mode 100644 index 00000000000..d8eb00f07da --- /dev/null +++ b/tests/cases/compiler/baseConstraintOfDecorator.ts @@ -0,0 +1,8 @@ +export function classExtender(superClass: TFunction, _instanceModifier: (instance: any, args: any[]) => void): TFunction { + return class decoratorFunc extends superClass { + constructor(...args: any[]) { + super(...args); + _instanceModifier(this, args); + } + }; +}