const BINDINGS_STORE_KEY = '__fnBindings__' ; /** Decorator "bind" allows to bind prototype method context to class instance */ export function bind < T extends Function > ( target , propertyKey , descriptor ) { if ( ! descriptor || ( typeof descriptor . value !== 'function' ) ) { throw new TypeError ( 'Only class methods can be decorated via @bind' ) ; } const fn = descriptor . value ; return { enumerable : descriptor . enumerable , configurable : descriptor . configurable , get ( ) { if ( ! this || this === target || Object . hasOwnProperty . call ( this , 'constructor' ) ) { return fn ; } let bindings = this [ BINDINGS_STORE_KEY ] ; if ( ! bindings ) { bindings = this [ BINDINGS_STORE_KEY ] = new WeakMap < T , T > ( ) ; } if ( ! bindings . has ( fn ) ) { bindings . set ( fn , fn . bind ( this ) ) ; } return bindings . get ( fn ) ; } , set ( value ) { Object . defineProperty ( this , propertyKey , { writable : true , enumerable : false , configurable : true , value } ) ; } } ; }