@@ -3210,7 +3210,10 @@ export class FunctionPrototype extends DeclaredElement {
32103210 get isBound ( ) : bool {
32113211 var parent = this . parent ;
32123212 return parent . kind == ElementKind . CLASS
3213- || parent . kind == ElementKind . PROPERTY_PROTOTYPE && parent . parent . kind == ElementKind . CLASS ;
3213+ || parent . kind == ElementKind . PROPERTY_PROTOTYPE && (
3214+ parent . parent . kind == ElementKind . CLASS ||
3215+ parent . parent . kind == ElementKind . INTERFACE
3216+ ) ;
32143217 }
32153218
32163219 /** Creates a clone of this prototype that is bound to a concrete class instead. */
@@ -3415,8 +3418,9 @@ export class Function extends TypedElement {
34153418 /** Finalizes the function once compiled, releasing no longer needed resources. */
34163419 finalize ( module : Module , ref : FunctionRef ) : void {
34173420 this . ref = ref ;
3418- assert ( ! this . breakStack || ! this . breakStack . length ) ; // internal error
3419- this . breakStack = null ;
3421+ var breakStack = this . breakStack ;
3422+ assert ( ! breakStack || ! breakStack . length ) ; // internal error
3423+ this . breakStack = breakStack = null ;
34203424 this . breakLabel = null ;
34213425 this . tempI32s = this . tempI64s = this . tempF32s = this . tempF64s = null ;
34223426 if ( this . program . options . sourceMap ) {
@@ -3571,13 +3575,18 @@ export class PropertyPrototype extends DeclaredElement {
35713575 getterPrototype : FunctionPrototype | null = null ;
35723576 /** Setter prototype. */
35733577 setterPrototype : FunctionPrototype | null = null ;
3578+ /** Property instance, if resolved. */
3579+ instance : Property | null = null ;
3580+
3581+ /** Clones of this prototype that are bound to specific classes. */
3582+ private boundPrototypes : Map < Class , PropertyPrototype > | null = null ;
35743583
35753584 /** Constructs a new property prototype. */
35763585 constructor (
35773586 /** Simple name. */
35783587 name : string ,
3579- /** Parent class. */
3580- parent : ClassPrototype ,
3588+ /** Parent element. Either a class prototype or instance . */
3589+ parent : Element ,
35813590 /** Declaration of the getter or setter introducing the property. */
35823591 firstDeclaration : FunctionDeclaration
35833592 ) {
@@ -3596,6 +3605,42 @@ export class PropertyPrototype extends DeclaredElement {
35963605 lookup ( name : string ) : Element | null {
35973606 return this . parent . lookup ( name ) ;
35983607 }
3608+
3609+ /** Tests if this prototype is bound to a class. */
3610+ get isBound ( ) : bool {
3611+ switch ( this . parent . kind ) {
3612+ case ElementKind . CLASS :
3613+ case ElementKind . INTERFACE : return true ;
3614+ }
3615+ return false ;
3616+ }
3617+
3618+ /** Creates a clone of this prototype that is bound to a concrete class instead. */
3619+ toBound ( classInstance : Class ) : PropertyPrototype {
3620+ assert ( this . is ( CommonFlags . INSTANCE ) ) ;
3621+ assert ( ! this . isBound ) ;
3622+ var boundPrototypes = this . boundPrototypes ;
3623+ if ( ! boundPrototypes ) this . boundPrototypes = boundPrototypes = new Map ( ) ;
3624+ else if ( boundPrototypes . has ( classInstance ) ) return assert ( boundPrototypes . get ( classInstance ) ) ;
3625+ var firstDeclaration = this . declaration ;
3626+ assert ( firstDeclaration . kind == NodeKind . METHODDECLARATION ) ;
3627+ var bound = new PropertyPrototype (
3628+ this . name ,
3629+ classInstance , // !
3630+ < MethodDeclaration > firstDeclaration
3631+ ) ;
3632+ bound . flags = this . flags ;
3633+ var getterPrototype = this . getterPrototype ;
3634+ if ( getterPrototype ) {
3635+ bound . getterPrototype = getterPrototype . toBound ( classInstance ) ;
3636+ }
3637+ var setterPrototype = this . setterPrototype ;
3638+ if ( setterPrototype ) {
3639+ bound . setterPrototype = setterPrototype . toBound ( classInstance ) ;
3640+ }
3641+ boundPrototypes . set ( classInstance , bound ) ;
3642+ return bound ;
3643+ }
35993644}
36003645
36013646/** A resolved property. */
@@ -3631,7 +3676,9 @@ export class Property extends VariableLikeElement {
36313676 this . prototype = prototype ;
36323677 this . flags = prototype . flags ;
36333678 this . decoratorFlags = prototype . decoratorFlags ;
3634- registerConcreteElement ( this . program , this ) ;
3679+ if ( this . is ( CommonFlags . INSTANCE ) ) {
3680+ registerConcreteElement ( this . program , this ) ;
3681+ }
36353682 }
36363683
36373684 /* @override */
@@ -3860,8 +3907,8 @@ export class Class extends TypedElement {
38603907 return lengthField !== null && (
38613908 lengthField . kind == ElementKind . FIELD ||
38623909 (
3863- lengthField . kind == ElementKind . PROPERTY &&
3864- ( < Property > lengthField ) . getterInstance !== null // TODO: resolve & check type?
3910+ lengthField . kind == ElementKind . PROPERTY_PROTOTYPE &&
3911+ ( < PropertyPrototype > lengthField ) . getterPrototype !== null // TODO: resolve & check type?
38653912 )
38663913 ) && (
38673914 this . lookupOverload ( OperatorKind . INDEXED_GET ) !== null ||
@@ -3908,9 +3955,10 @@ export class Class extends TypedElement {
39083955 throw new Error ( "type argument count mismatch" ) ;
39093956 }
39103957 if ( numTypeArguments ) {
3911- if ( ! this . contextualTypeArguments ) this . contextualTypeArguments = new Map ( ) ;
3958+ let contextualTypeArguments = this . contextualTypeArguments ;
3959+ if ( ! contextualTypeArguments ) this . contextualTypeArguments = contextualTypeArguments = new Map ( ) ;
39123960 for ( let i = 0 ; i < numTypeArguments ; ++ i ) {
3913- this . contextualTypeArguments . set ( typeParameters [ i ] . name . text , typeArguments [ i ] ) ;
3961+ contextualTypeArguments . set ( typeParameters [ i ] . name . text , typeArguments [ i ] ) ;
39143962 }
39153963 }
39163964 } else if ( typeParameters !== null && typeParameters . length > 0 ) {
@@ -4402,8 +4450,8 @@ export function mangleInternalName(name: string, parent: Element, isInstance: bo
44024450 assert ( ! isInstance ) ;
44034451 return parent . internalName + INNER_DELIMITER + name ;
44044452 }
4405- case ElementKind . PROPERTY_PROTOTYPE :
4406- case ElementKind . PROPERTY : {
4453+ case ElementKind . PROPERTY_PROTOTYPE : // properties are just containers
4454+ case ElementKind . PROPERTY : { //
44074455 parent = parent . parent ;
44084456 // fall-through
44094457 }
0 commit comments