@@ -568,7 +568,7 @@ namespace ts {
568568 /**
569569 * Tests whether we should emit a __decorate call for a class declaration.
570570 */
571- function shouldEmitDecorateCallForClass ( node : ClassDeclaration ) {
571+ function shouldEmitDecorateCallForClass ( node : ClassDeclaration | ClassExpression ) {
572572 if ( node . decorators && node . decorators . length > 0 ) {
573573 return true ;
574574 }
@@ -588,7 +588,7 @@ namespace ts {
588588 return parameter . decorators !== undefined && parameter . decorators . length > 0 ;
589589 }
590590
591- function getClassFacts ( node : ClassDeclaration , staticProperties : readonly PropertyDeclaration [ ] ) {
591+ function getClassFacts ( node : ClassDeclaration | ClassExpression , staticProperties : readonly PropertyDeclaration [ ] ) {
592592 let facts = ClassFacts . None ;
593593 if ( some ( staticProperties ) ) facts |= ClassFacts . HasStaticInitializedProperties ;
594594 const extendsClauseElement = getEffectiveBaseTypeNode ( node ) ;
@@ -634,8 +634,8 @@ namespace ts {
634634
635635
636636 // Write any decorators of the node.
637- addClassElementDecorationStatements ( statements , node , /*isStatic*/ false ) ;
638- addClassElementDecorationStatements ( statements , node , /*isStatic*/ true ) ;
637+ addClassElementDecorationStatements ( statements , createClassPrototype ( factory . getDeclarationName ( node ) ) , node , /*isStatic*/ false ) ;
638+ addClassElementDecorationStatements ( statements , factory . getDeclarationName ( node ) , node , /*isStatic*/ true ) ;
639639 addConstructorDecorationStatement ( statements , node ) ;
640640
641641 if ( facts & ClassFacts . UseImmediatelyInvokedFunctionExpression ) {
@@ -879,6 +879,9 @@ namespace ts {
879879 return visitEachChild ( node , visitor , context ) ;
880880 }
881881
882+ const staticProperties = getProperties ( node , /*requireInitializer*/ true , /*isStatic*/ true ) ;
883+ const facts = getClassFacts ( node , staticProperties ) ;
884+
882885 const classExpression = factory . createClassExpression (
883886 /*decorators*/ undefined ,
884887 /*modifiers*/ undefined ,
@@ -888,6 +891,14 @@ namespace ts {
888891 transformClassMembers ( node )
889892 ) ;
890893
894+ if ( facts & ClassFacts . HasMemberDecorators ) {
895+ const temp = factory . createTempVariable ( hoistVariableDeclaration ) ;
896+ const expressions : Expression [ ] = [ factory . createAssignment ( temp , classExpression ) ] ;
897+ addClassElementDecorationExpressions ( expressions , createClassPrototype ( temp ) , node , /*isStatic*/ false ) ;
898+ addClassElementDecorationExpressions ( expressions , temp , node , /*isStatic*/ true ) ;
899+ return factory . inlineExpressions ( [ ...expressions , temp ] ) ;
900+ }
901+
891902 setOriginalNode ( classExpression , node ) ;
892903 setTextRange ( classExpression , node ) ;
893904
@@ -1123,31 +1134,44 @@ namespace ts {
11231134 return decoratorExpressions ;
11241135 }
11251136
1137+ /**
1138+ * Generates expressions used to apply decorators to either the static or instance member of a class.
1139+ *
1140+ * @param target
1141+ * @param node The class node.
1142+ * @param isStatic A value indicating whether to generate expressions for static or instance members.
1143+ */
1144+ function addClassElementDecorationExpressions ( expressions : Expression [ ] , target : Identifier | PropertyAccessExpression , node : ClassLikeDeclaration , isStatic : boolean ) {
1145+ addRange ( expressions , map ( generateClassElementDecorationExpressions ( target , node , isStatic ) , expression => expression ) ) ;
1146+ }
1147+
11261148 /**
11271149 * Generates statements used to apply decorators to either the static or instance members
11281150 * of a class.
11291151 *
1152+ * @param target
11301153 * @param node The class node.
11311154 * @param isStatic A value indicating whether to generate statements for static or
11321155 * instance members.
11331156 */
1134- function addClassElementDecorationStatements ( statements : Statement [ ] , node : ClassDeclaration , isStatic : boolean ) {
1135- addRange ( statements , map ( generateClassElementDecorationExpressions ( node , isStatic ) , expressionToStatement ) ) ;
1157+ function addClassElementDecorationStatements ( statements : Statement [ ] , target : Identifier | PropertyAccessExpression , node : ClassLikeDeclaration , isStatic : boolean ) {
1158+ addRange ( statements , map ( generateClassElementDecorationExpressions ( target , node , isStatic ) , expressionToStatement ) ) ;
11361159 }
11371160
11381161 /**
11391162 * Generates expressions used to apply decorators to either the static or instance members
11401163 * of a class.
11411164 *
1165+ * @param target
11421166 * @param node The class node.
11431167 * @param isStatic A value indicating whether to generate expressions for static or
11441168 * instance members.
11451169 */
1146- function generateClassElementDecorationExpressions ( node : ClassExpression | ClassDeclaration , isStatic : boolean ) {
1170+ function generateClassElementDecorationExpressions ( target : Identifier | PropertyAccessExpression , node : ClassExpression | ClassDeclaration , isStatic : boolean ) {
11471171 const members = getDecoratedClassElements ( node , isStatic ) ;
11481172 let expressions : Expression [ ] | undefined ;
11491173 for ( const member of members ) {
1150- const expression = generateClassElementDecorationExpression ( node , member ) ;
1174+ const expression = generateClassElementDecorationExpression ( target , node , member ) ;
11511175 if ( expression ) {
11521176 if ( ! expressions ) {
11531177 expressions = [ expression ] ;
@@ -1163,10 +1187,11 @@ namespace ts {
11631187 /**
11641188 * Generates an expression used to evaluate class element decorators at runtime.
11651189 *
1190+ * @param target
11661191 * @param node The class node that contains the member.
11671192 * @param member The class member.
11681193 */
1169- function generateClassElementDecorationExpression ( node : ClassExpression | ClassDeclaration , member : ClassElement ) {
1194+ function generateClassElementDecorationExpression ( target : Identifier | PropertyAccessExpression , node : ClassExpression | ClassDeclaration , member : ClassElement ) {
11701195 const allDecorators = getAllDecoratorsOfClassElement ( node , member ) ;
11711196 const decoratorExpressions = transformAllDecoratorsOfDeclaration ( member , node , allDecorators ) ;
11721197 if ( ! decoratorExpressions ) {
@@ -1204,7 +1229,6 @@ namespace ts {
12041229 // ], C.prototype, "prop");
12051230 //
12061231
1207- const prefix = getClassMemberPrefix ( node , member ) ;
12081232 const memberName = getExpressionForPropertyName ( member , /*generateNameForComputedPropertyName*/ true ) ;
12091233 const descriptor = languageVersion > ScriptTarget . ES3
12101234 ? member . kind === SyntaxKind . PropertyDeclaration
@@ -1219,7 +1243,7 @@ namespace ts {
12191243
12201244 const helper = emitHelpers ( ) . createDecorateHelper (
12211245 decoratorExpressions ,
1222- prefix ,
1246+ target ,
12231247 memberName ,
12241248 descriptor
12251249 ) ;
@@ -3151,14 +3175,8 @@ namespace ts {
31513175 }
31523176 }
31533177
3154- function getClassPrototype ( node : ClassExpression | ClassDeclaration ) {
3155- return factory . createPropertyAccessExpression ( factory . getDeclarationName ( node ) , "prototype" ) ;
3156- }
3157-
3158- function getClassMemberPrefix ( node : ClassExpression | ClassDeclaration , member : ClassElement ) {
3159- return hasSyntacticModifier ( member , ModifierFlags . Static )
3160- ? factory . getDeclarationName ( node )
3161- : getClassPrototype ( node ) ;
3178+ function createClassPrototype ( expression : Expression ) {
3179+ return factory . createPropertyAccessExpression ( expression , "prototype" ) ;
31623180 }
31633181
31643182 function enableSubstitutionForNonQualifiedEnumMembers ( ) {
0 commit comments