@@ -1543,21 +1543,28 @@ namespace ts {
1543
1543
* @param node The ClassExpression or ClassDeclaration node.
1544
1544
*/
1545
1545
function addClassMembers ( statements : Statement [ ] , node : ClassExpression | ClassDeclaration ) : void {
1546
+ if ( ! node . members . length ) {
1547
+ return ;
1548
+ }
1549
+
1550
+ const prototypeStoragePlacement = statements . length ;
1551
+ let prototypeStorageName : Identifier | PropertyAccessExpression ;
1552
+
1546
1553
for ( const member of node . members ) {
1547
1554
switch ( member . kind ) {
1548
1555
case SyntaxKind . SemicolonClassElement :
1549
1556
statements . push ( transformSemicolonClassElementToStatement ( < SemicolonClassElement > member ) ) ;
1550
1557
break ;
1551
1558
1552
1559
case SyntaxKind . MethodDeclaration :
1553
- statements . push ( transformClassMethodDeclarationToStatement ( getClassMemberPrefix ( node , member ) , < MethodDeclaration > member , node ) ) ;
1560
+ statements . push ( transformClassMethodDeclarationToStatement ( getClassMemberPrefix ( node , member , getPrototypeStorageName ) , < MethodDeclaration > member , node ) ) ;
1554
1561
break ;
1555
1562
1556
1563
case SyntaxKind . GetAccessor :
1557
1564
case SyntaxKind . SetAccessor :
1558
1565
const accessors = getAllAccessorDeclarations ( node . members , < AccessorDeclaration > member ) ;
1559
1566
if ( member === accessors . firstAccessor ) {
1560
- statements . push ( transformAccessorsToStatement ( getClassMemberPrefix ( node , member ) , accessors , node ) ) ;
1567
+ statements . push ( transformAccessorsToStatement ( getClassMemberPrefix ( node , member , getPrototypeStorageName ) , accessors , node ) ) ;
1561
1568
}
1562
1569
1563
1570
break ;
@@ -1571,6 +1578,51 @@ namespace ts {
1571
1578
break ;
1572
1579
}
1573
1580
}
1581
+
1582
+ /**
1583
+ * Lazily creates the way class members will access the class prototype.
1584
+ */
1585
+ function getPrototypeStorageName ( ) {
1586
+ if ( prototypeStorageName ) {
1587
+ return prototypeStorageName ;
1588
+ }
1589
+
1590
+ const originalPrototypeAccess = createPropertyAccess ( getInternalName ( node ) , "prototype" ) ;
1591
+
1592
+ // If the class has exactly one non-static member, it'll access prototype members on itself:
1593
+ // ClassName.prototype.member = ...
1594
+ if ( containsExactlyOne ( node . members , classMemberAssignsToPrototype ) ) {
1595
+ prototypeStorageName = originalPrototypeAccess ;
1596
+ return prototypeStorageName ;
1597
+ }
1598
+
1599
+ // Since it has multiple non-static members, it'll store that prototype as a variable that can be minified:
1600
+ // var proto = ClassName.prototype;
1601
+ // proto.memberOne = ...
1602
+ // proto.memberTwo = ...
1603
+ prototypeStorageName = createUniqueName ( "proto" ) ;
1604
+
1605
+ statements . splice (
1606
+ prototypeStoragePlacement ,
1607
+ 0 ,
1608
+ createVariableStatement (
1609
+ /*modifiers*/ undefined ,
1610
+ createVariableDeclarationList ( [
1611
+ createVariableDeclaration (
1612
+ prototypeStorageName ,
1613
+ /*type*/ undefined ,
1614
+ originalPrototypeAccess ,
1615
+ )
1616
+ ] )
1617
+ )
1618
+ ) ;
1619
+
1620
+ return prototypeStorageName ;
1621
+ }
1622
+ }
1623
+
1624
+ function classMemberAssignsToPrototype ( node : ClassElement ) {
1625
+ return ! hasModifier ( node , ModifierFlags . Static ) && ! isConstructorDeclaration ( node ) ;
1574
1626
}
1575
1627
1576
1628
/**
@@ -4299,10 +4351,10 @@ namespace ts {
4299
4351
return node ;
4300
4352
}
4301
4353
4302
- function getClassMemberPrefix ( node : ClassExpression | ClassDeclaration , member : ClassElement ) {
4303
- return hasModifier ( member , ModifierFlags . Static )
4354
+ function getClassMemberPrefix ( node : ClassExpression | ClassDeclaration , member : ClassElement , getPrototypeStorageName : ( ) => LeftHandSideExpression ) {
4355
+ return member && hasModifier ( member , ModifierFlags . Static )
4304
4356
? getInternalName ( node )
4305
- : createPropertyAccess ( getInternalName ( node ) , "prototype" ) ;
4357
+ : getPrototypeStorageName ( ) ;
4306
4358
}
4307
4359
4308
4360
function hasSynthesizedDefaultSuperCall ( constructor : ConstructorDeclaration | undefined , hasExtendsClause : boolean ) {
0 commit comments