@@ -2532,7 +2532,6 @@ module ts {
25322532 //
25332533 // The emit for the decorated computed property decorator is:
25342534 //
2535- // _a = typeof _a == "symbol" ? _a : String(_a);
25362535 // Object.defineProperty(C.prototype, _a, __decorate([dec], C.prototype, _a, Object.getOwnPropertyDescriptor(C.prototype, _a)));
25372536 //
25382537 if ( nodeIsDecorated ( node . parent ) ) {
@@ -4887,83 +4886,76 @@ module ts {
48874886 }
48884887
48894888 function emitClassDeclarationForES6AndHigher ( node : ClassDeclaration ) {
4890- if ( isES6ModuleMemberDeclaration ( node ) ) {
4891- write ( "export " ) ;
4892-
4893- if ( node . flags & NodeFlags . Default ) {
4894- write ( "default " ) ;
4895- }
4896- }
4897-
48984889 let thisNodeIsDecorated = nodeIsDecorated ( node ) ;
4899- let thisNodeOrChildrenAreDecorated = nodeOrChildIsDecorated ( node ) ;
4900- if ( thisNodeOrChildrenAreDecorated ) {
4901- // When decorations are applied to a class, they may need to introduce new
4902- // temporary variables or even replace the class constructor. As such, we
4903- // need to ensure all decorators are applied before the declaration is
4904- // visible, and avoid unnecessarily leaking internal temporary state to the
4905- // module or global scope.
4890+ if ( thisNodeIsDecorated ) {
4891+ // To preserve the correct runtime semantics when decorators are applied to the class,
4892+ // the emit needs to follow one of the following rules:
49064893 //
4907- // We also may need to alias the class declaration to avoid a pitfall in
4908- // ES6 classes due to the fact that the class identifier is doubly-bound both
4909- // in its outer scope and its class body. A class decorator could replace the
4910- // class constructor. In that case, we need to emit the class as a class expression
4911- // without an identifier, and assign that name later using Object.defineProperty
4912- // (since the `name` property of a class/function is `writable:false` but
4913- // `configurable:true`).
4914- //
4894+ // * For a local class declaration:
49154895 //
4916- // Given the class:
4896+ // @dec class C {
4897+ // }
49174898 //
4918- // @dec
4919- // class C {
4920- // static x() {}
4921- // y() { C.x(); }
4922- // }
4899+ // The emit should be:
4900+ //
4901+ // let C = class {
4902+ // };
4903+ // Object.defineProperty(C, "name", { value: "C", configurable: true });
4904+ // C = __decorate([dec], C);
4905+ //
4906+ // * For an exported class declaration:
4907+ //
4908+ // @dec export class C {
4909+ // }
4910+ //
4911+ // The emit should be:
4912+ //
4913+ // export let C = class {
4914+ // };
4915+ // Object.defineProperty(C, "name", { value: "C", configurable: true });
4916+ // C = __decorate([dec], C);
4917+ //
4918+ // * For a default export of a class declaration with a name:
4919+ //
4920+ // @dec default export class C {
4921+ // }
4922+ //
4923+ // The emit should be:
4924+ //
4925+ // let C = class {
4926+ // }
4927+ // Object.defineProperty(C, "name", { value: "C", configurable: true });
4928+ // C = __decorate([dec], C);
4929+ // export default C;
4930+ //
4931+ // * For a default export of a class declaration without a name:
4932+ //
4933+ // @dec default export class {
4934+ // }
49234935 //
4924- // The ES6 emit for the is :
4936+ // The emit should be :
49254937 //
4926- // let C = () => {
4927- // let C = class {
4928- // static x() {}
4929- // y() { C.x(); }
4930- // }
4931- // Object.defineProperty(C, "name", { value: "C", configurable: true });
4932- // C = __decorate([dec], C);
4933- // return C;
4934- // }();
4938+ // let _default = class {
4939+ // }
4940+ // _default = __decorate([dec], _default);
4941+ // export default _default;
49354942 //
49364943
4937- // if this is not an export, emit the name
4938- if ( ! ( node . flags & NodeFlags . Default ) ) {
4939- write ( "let " ) ;
4940- emitDeclarationName ( node ) ;
4941- write ( " = " ) ;
4944+ if ( isES6ModuleMemberDeclaration ( node ) && ! ( node . flags & NodeFlags . Default ) ) {
4945+ write ( "export " ) ;
49424946 }
49434947
4944- // begin the IIFE
4945- write ( "() => {" ) ;
4946-
4947- // keep our generated state private
4948- var saveTempCount = tempCount ;
4949- var saveTempVariables = tempVariables ;
4950- var saveTempParameters = tempParameters ;
4951- var saveGeneratedComputedPropertyNames = generatedComputedPropertyNames ;
4952- tempCount = 0 ;
4953- tempVariables = undefined ;
4954- tempParameters = undefined ;
4955- generatedComputedPropertyNames = undefined ;
4956-
4957- increaseIndent ( ) ;
4958- writeLine ( ) ;
4959-
4960- if ( thisNodeIsDecorated ) {
4961- write ( "let " ) ;
4962- emitDeclarationName ( node ) ;
4963- write ( " = " ) ;
4948+ write ( "let " ) ;
4949+ emitDeclarationName ( node ) ;
4950+ write ( " = " ) ;
4951+ }
4952+ else if ( isES6ModuleMemberDeclaration ( node ) ) {
4953+ write ( "export " ) ;
4954+ if ( node . flags & NodeFlags . Default ) {
4955+ write ( "default " ) ;
49644956 }
49654957 }
4966-
4958+
49674959 write ( "class" ) ;
49684960
49694961 // check if this is an "export default class" as it may not have a name. Do not emit the name if the class is decorated.
@@ -4996,14 +4988,17 @@ module ts {
49964988 // }
49974989 // Object.defineProperty(C, "name", { value: "C", configurable: true });
49984990 //
4999- if ( ( node . name || ! ( node . flags & NodeFlags . Default ) ) && thisNodeIsDecorated ) {
5000- writeLine ( ) ;
5001- write ( "Object.defineProperty(" ) ;
5002- emitDeclarationName ( node ) ;
5003- write ( ", \"name\", { value: \"" ) ;
5004- emitDeclarationName ( node ) ;
5005- write ( "\", configurable: true });" ) ;
5006- writeLine ( ) ;
4991+ if ( thisNodeIsDecorated ) {
4992+ write ( ";" ) ;
4993+ if ( node . name ) {
4994+ writeLine ( ) ;
4995+ write ( "Object.defineProperty(" ) ;
4996+ emitDeclarationName ( node ) ;
4997+ write ( ", \"name\", { value: \"" ) ;
4998+ emitDeclarationName ( node ) ;
4999+ write ( "\", configurable: true });" ) ;
5000+ writeLine ( ) ;
5001+ }
50075002 }
50085003
50095004 // Emit static property assignment. Because classDeclaration is lexically evaluated,
@@ -5013,29 +5008,11 @@ module ts {
50135008 // a lexical declaration such as a LexicalDeclaration or a ClassDeclaration.
50145009 writeLine ( ) ;
50155010 emitMemberAssignments ( node , NodeFlags . Static ) ;
5011+ emitDecoratorsOfClass ( node ) ;
50165012
5017- if ( thisNodeOrChildrenAreDecorated ) {
5018- writeLine ( ) ;
5019- emitDecoratorsOfClass ( node ) ;
5020-
5021- write ( "return " ) ;
5022- emitDeclarationName ( node ) ;
5023- write ( ";" ) ;
5024-
5025- emitTempDeclarations ( /*newLine*/ true ) ;
5026- tempCount = saveTempCount ;
5027- tempVariables = saveTempVariables ;
5028- tempParameters = saveTempParameters ;
5029- generatedComputedPropertyNames = saveGeneratedComputedPropertyNames ;
5030-
5031- decreaseIndent ( ) ;
5032- writeLine ( ) ;
5033- write ( "}();" ) ;
5034- }
5035-
5036- // If this is an exported class, but not on the top level (i.e. on an internal
5037- // module), export it
50385013 if ( ! isES6ModuleMemberDeclaration ( node ) && ( node . flags & NodeFlags . Export ) ) {
5014+ // If this is an exported class, but not on the top level (i.e. on an internal
5015+ // module), export it
50395016 writeLine ( ) ;
50405017 emitStart ( node ) ;
50415018 emitModuleMemberName ( node ) ;
@@ -5044,6 +5021,13 @@ module ts {
50445021 emitEnd ( node ) ;
50455022 write ( ";" ) ;
50465023 }
5024+ else if ( isES6ModuleMemberDeclaration ( node ) && ( node . flags & NodeFlags . Default ) && thisNodeIsDecorated ) {
5025+ // if this is a top level default export of decorated class, write the export after the declaration.
5026+ writeLine ( ) ;
5027+ write ( "export default " ) ;
5028+ emitDeclarationName ( node ) ;
5029+ write ( ";" ) ;
5030+ }
50475031 }
50485032
50495033 function emitClassDeclarationBelowES6 ( node : ClassDeclaration ) {
@@ -5152,16 +5136,15 @@ module ts {
51525136 //
51535137 // The emit for the class is:
51545138 //
5155- // C = __decorate([dec], C, void 0, C );
5139+ // C = __decorate([dec], C);
51565140 //
51575141
5142+ writeLine ( ) ;
51585143 emitStart ( node ) ;
51595144 emitDeclarationName ( node ) ;
51605145 write ( " = " ) ;
51615146 emitDecorateStart ( node . decorators ) ;
51625147 emitDeclarationName ( node ) ;
5163- write ( ", void 0, " ) ;
5164- emitDeclarationName ( node ) ;
51655148 write ( ");" ) ;
51665149 emitEnd ( node ) ;
51675150 writeLine ( ) ;
@@ -5236,6 +5219,7 @@ module ts {
52365219 // __decorate([dec], C.prototype, "prop");
52375220 //
52385221
5222+ writeLine ( ) ;
52395223 emitStart ( member ) ;
52405224 if ( member . kind !== SyntaxKind . PropertyDeclaration ) {
52415225 write ( "Object.defineProperty(" ) ;
@@ -5286,7 +5270,7 @@ module ts {
52865270 //
52875271 // The emit for a constructor is:
52885272 //
5289- // __decorate([dec], C.prototype , void 0, 0);
5273+ // __decorate([dec], C, void 0, 0);
52905274 //
52915275 // The emit for a parameter is:
52925276 //
@@ -5297,16 +5281,18 @@ module ts {
52975281 // __decorate([dec], C.prototype, "accessor", 0);
52985282 //
52995283
5284+ writeLine ( ) ;
53005285 emitStart ( parameter ) ;
53015286 emitDecorateStart ( parameter . decorators ) ;
53025287 emitStart ( parameter . name ) ;
5303- emitClassMemberPrefix ( node , member ) ;
5304- write ( ", " ) ;
53055288
53065289 if ( member . kind === SyntaxKind . Constructor ) {
5307- write ( "void 0" ) ;
5290+ emitDeclarationName ( node ) ;
5291+ write ( ", void 0" ) ;
53085292 }
53095293 else {
5294+ emitClassMemberPrefix ( node , member ) ;
5295+ write ( ", " ) ;
53105296 emitExpressionForPropertyName ( member . name ) ;
53115297 }
53125298
@@ -6028,17 +6014,17 @@ module ts {
60286014 if ( ! decorateEmitted && resolver . getNodeCheckFlags ( node ) & NodeCheckFlags . EmitDecorate ) {
60296015 writeHelper ( `
60306016var __decorate = this.__decorate || function (decorators, target, key, value) {
6031- var kind = typeof value;
6017+ var kind = typeof (arguments.length == 2 ? value = target : value) ;
60326018 for (var i = decorators.length - 1; i >= 0; --i) {
60336019 var decorator = decorators[i];
60346020 switch (kind) {
6035- case "object ": value = decorator(target, key, value) || value; break;
6021+ case "function ": value = decorator(value) || value; break;
60366022 case "number": decorator(target, key, value); break;
6037- case "function": target = decorator(target) || target; break;
60386023 case "undefined": decorator(target, key); break;
6024+ case "object": value = decorator(target, key, value) || value; break;
60396025 }
60406026 }
6041- return value || target ;
6027+ return value;
60426028};` ) ;
60436029 decorateEmitted = true ;
60446030 }
0 commit comments