Fix TypeErrors from decorated class emit.

This commit is contained in:
Ron Buckton
2016-05-10 12:13:05 -07:00
parent 2ef748308a
commit 6e16a7eae6
6 changed files with 33 additions and 22 deletions
+5
View File
@@ -16854,6 +16854,11 @@ namespace ts {
function isValueAliasDeclaration(node: Node): boolean {
node = getSourceTreeNode(node);
if (node === undefined) {
// A synthesized node comes from an emit transformation and is always a value.
return true;
}
switch (node.kind) {
case SyntaxKind.ImportEqualsDeclaration:
case SyntaxKind.ImportClause:
@@ -735,15 +735,7 @@ namespace ts {
const classDecl = original as ClassDeclaration;
if (classDecl.name) {
const statements = [node];
// Avoid emitting a default because a decorated default-exported class will have been rewritten in the TS transformer to
// a decorator assignment (`foo = __decorate(...)`) followed by a separate default export declaration (`export default foo`).
// We will eventually take care of that default export assignment when we transform the generated default export declaration.
if (hasModifier(classDecl, ModifierFlags.Export) && !hasModifier(classDecl, ModifierFlags.Default)) {
addExportMemberAssignment(statements, classDecl)
}
addExportMemberAssignments(statements, classDecl.name);
return statements;
}
}
+24 -11
View File
@@ -420,6 +420,26 @@ namespace ts {
}
}
/**
* Tests whether we should emit a __decorate call for a class declaration.
*/
function shouldEmitDecorateCallForClass(node: ClassDeclaration) {
if (node.decorators && node.decorators.length > 0) {
return true;
}
const constructor = getFirstConstructorWithBody(node);
if (constructor) {
for (const parameter of constructor.parameters) {
if (parameter.decorators && parameter.decorators.length > 0) {
return true;
}
}
}
return false;
}
/**
* Transforms a class declaration with TypeScript syntax into compatible ES6.
*
@@ -434,6 +454,7 @@ namespace ts {
function visitClassDeclaration(node: ClassDeclaration): VisitResult<Statement> {
const staticProperties = getInitializedProperties(node, /*isStatic*/ true);
const hasExtendsClause = getClassExtendsHeritageClauseElement(node) !== undefined;
const isDecoratedClass = shouldEmitDecorateCallForClass(node);
let decoratedClassAlias: Identifier;
// emit name if
@@ -446,7 +467,7 @@ namespace ts {
}
const statements: Statement[] = [];
if (!node.decorators) {
if (!isDecoratedClass) {
// ${modifiers} class ${name} ${heritageClauses} {
// ${members}
// }
@@ -491,7 +512,7 @@ namespace ts {
if (isNamespaceExport(node)) {
addExportMemberAssignment(statements, node);
}
else if (node.decorators) {
else if (isDecoratedClass) {
if (isDefaultExternalModuleExport(node)) {
statements.push(createExportDefault(getLocalName(node)));
}
@@ -644,19 +665,11 @@ namespace ts {
/*location*/ location);
}
// When emitting as a *default* export, we'll add a subsequent `export default` statement,
// so we should only be creating a local binding without any modifiers.
// Otherwise, we need preserve and visit all the modifiers.
const bindingModifiers =
isDefaultExternalModuleExport(node)
? undefined
: visitNodes(node.modifiers, visitor, isModifier);
// let ${name} = ${classExpression};
addNode(statements,
setOriginalNode(
createVariableStatement(
bindingModifiers,
/*modifiers*/ undefined,
createLetDeclarationList([
createVariableDeclaration(
getDeclarationName(node, /*allowComments*/ true),
@@ -14,9 +14,10 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
export let C = class C {
let C = class C {
};
C = __decorate([
dec
], C);
export { C };
let c = new C();
@@ -17,11 +17,12 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
let C_1;
export let C = C_1 = class C {
let C = C_1 = class C {
static x() { return C_1.y; }
};
C.y = 1;
C = C_1 = __decorate([
dec
], C);
export { C };
let c = new C();
@@ -49,7 +49,6 @@ var C = (function (_super) {
}
return C;
}(_0_ts_1.base));
exports.C = C;
C = __decorate([
__param(0, _0_ts_2.foo)
], C);