@@ -2532,7 +2532,6 @@ module ts {
2532
2532
//
2533
2533
// The emit for the decorated computed property decorator is:
2534
2534
//
2535
- // _a = typeof _a == "symbol" ? _a : String(_a);
2536
2535
// Object.defineProperty(C.prototype, _a, __decorate([dec], C.prototype, _a, Object.getOwnPropertyDescriptor(C.prototype, _a)));
2537
2536
//
2538
2537
if ( nodeIsDecorated ( node . parent ) ) {
@@ -4887,83 +4886,76 @@ module ts {
4887
4886
}
4888
4887
4889
4888
function emitClassDeclarationForES6AndHigher ( node : ClassDeclaration ) {
4890
- if ( isES6ModuleMemberDeclaration ( node ) ) {
4891
- write ( "export " ) ;
4892
-
4893
- if ( node . flags & NodeFlags . Default ) {
4894
- write ( "default " ) ;
4895
- }
4896
- }
4897
-
4898
4889
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:
4906
4893
//
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:
4915
4895
//
4916
- // Given the class:
4896
+ // @dec class C {
4897
+ // }
4917
4898
//
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
+ // }
4923
4935
//
4924
- // The ES6 emit for the is :
4936
+ // The emit should be :
4925
4937
//
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;
4935
4942
//
4936
4943
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 " ) ;
4942
4946
}
4943
4947
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 " ) ;
4964
4956
}
4965
4957
}
4966
-
4958
+
4967
4959
write ( "class" ) ;
4968
4960
4969
4961
// 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 {
4996
4988
// }
4997
4989
// Object.defineProperty(C, "name", { value: "C", configurable: true });
4998
4990
//
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
+ }
5007
5002
}
5008
5003
5009
5004
// Emit static property assignment. Because classDeclaration is lexically evaluated,
@@ -5013,29 +5008,11 @@ module ts {
5013
5008
// a lexical declaration such as a LexicalDeclaration or a ClassDeclaration.
5014
5009
writeLine ( ) ;
5015
5010
emitMemberAssignments ( node , NodeFlags . Static ) ;
5011
+ emitDecoratorsOfClass ( node ) ;
5016
5012
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
5038
5013
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
5039
5016
writeLine ( ) ;
5040
5017
emitStart ( node ) ;
5041
5018
emitModuleMemberName ( node ) ;
@@ -5044,6 +5021,13 @@ module ts {
5044
5021
emitEnd ( node ) ;
5045
5022
write ( ";" ) ;
5046
5023
}
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
+ }
5047
5031
}
5048
5032
5049
5033
function emitClassDeclarationBelowES6 ( node : ClassDeclaration ) {
@@ -5152,16 +5136,15 @@ module ts {
5152
5136
//
5153
5137
// The emit for the class is:
5154
5138
//
5155
- // C = __decorate([dec], C, void 0, C );
5139
+ // C = __decorate([dec], C);
5156
5140
//
5157
5141
5142
+ writeLine ( ) ;
5158
5143
emitStart ( node ) ;
5159
5144
emitDeclarationName ( node ) ;
5160
5145
write ( " = " ) ;
5161
5146
emitDecorateStart ( node . decorators ) ;
5162
5147
emitDeclarationName ( node ) ;
5163
- write ( ", void 0, " ) ;
5164
- emitDeclarationName ( node ) ;
5165
5148
write ( ");" ) ;
5166
5149
emitEnd ( node ) ;
5167
5150
writeLine ( ) ;
@@ -5236,6 +5219,7 @@ module ts {
5236
5219
// __decorate([dec], C.prototype, "prop");
5237
5220
//
5238
5221
5222
+ writeLine ( ) ;
5239
5223
emitStart ( member ) ;
5240
5224
if ( member . kind !== SyntaxKind . PropertyDeclaration ) {
5241
5225
write ( "Object.defineProperty(" ) ;
@@ -5286,7 +5270,7 @@ module ts {
5286
5270
//
5287
5271
// The emit for a constructor is:
5288
5272
//
5289
- // __decorate([dec], C.prototype , void 0, 0);
5273
+ // __decorate([dec], C, void 0, 0);
5290
5274
//
5291
5275
// The emit for a parameter is:
5292
5276
//
@@ -5297,16 +5281,18 @@ module ts {
5297
5281
// __decorate([dec], C.prototype, "accessor", 0);
5298
5282
//
5299
5283
5284
+ writeLine ( ) ;
5300
5285
emitStart ( parameter ) ;
5301
5286
emitDecorateStart ( parameter . decorators ) ;
5302
5287
emitStart ( parameter . name ) ;
5303
- emitClassMemberPrefix ( node , member ) ;
5304
- write ( ", " ) ;
5305
5288
5306
5289
if ( member . kind === SyntaxKind . Constructor ) {
5307
- write ( "void 0" ) ;
5290
+ emitDeclarationName ( node ) ;
5291
+ write ( ", void 0" ) ;
5308
5292
}
5309
5293
else {
5294
+ emitClassMemberPrefix ( node , member ) ;
5295
+ write ( ", " ) ;
5310
5296
emitExpressionForPropertyName ( member . name ) ;
5311
5297
}
5312
5298
@@ -6028,17 +6014,17 @@ module ts {
6028
6014
if ( ! decorateEmitted && resolver . getNodeCheckFlags ( node ) & NodeCheckFlags . EmitDecorate ) {
6029
6015
writeHelper ( `
6030
6016
var __decorate = this.__decorate || function (decorators, target, key, value) {
6031
- var kind = typeof value;
6017
+ var kind = typeof (arguments.length == 2 ? value = target : value) ;
6032
6018
for (var i = decorators.length - 1; i >= 0; --i) {
6033
6019
var decorator = decorators[i];
6034
6020
switch (kind) {
6035
- case "object ": value = decorator(target, key, value) || value; break;
6021
+ case "function ": value = decorator(value) || value; break;
6036
6022
case "number": decorator(target, key, value); break;
6037
- case "function": target = decorator(target) || target; break;
6038
6023
case "undefined": decorator(target, key); break;
6024
+ case "object": value = decorator(target, key, value) || value; break;
6039
6025
}
6040
6026
}
6041
- return value || target ;
6027
+ return value;
6042
6028
};` ) ;
6043
6029
decorateEmitted = true ;
6044
6030
}
0 commit comments