@@ -105,6 +105,7 @@ export function Provides(target: Function) {
105105 }
106106}
107107
108+ let construct ;
108109/**
109110 * A decorator to tell the container that this class should its instantiation always handled by the Container.
110111 *
@@ -140,23 +141,25 @@ export function AutoWired(target: Function) {
140141 existingInjectedParameters . reverse ( ) ;
141142 const paramTypes : Array < any > =
142143 Reflect . getMetadata ( "design:paramtypes" , target ) ;
143- newConstructor = InjectorHanlder . decorateConstructor ( function ( ...args : any [ ] ) {
144+ newConstructor = InjectorHanlder . decorateConstructor ( function ioc_wrapper ( ...args : any [ ] ) {
144145 IoCContainer . assertInstantiable ( target ) ;
145146 let newArgs : Array < any > = args ? args . concat ( ) : new Array < any > ( ) ;
146147 for ( let index of existingInjectedParameters ) {
147148 if ( index >= newArgs . length ) {
148149 newArgs . push ( IoCContainer . get ( paramTypes [ index ] ) ) ;
149150 }
150151 }
151- IoCContainer . applyInjections ( this , target ) ;
152- target . apply ( this , newArgs ) ;
152+ let ret = construct ( target , newArgs , ioc_wrapper ) ;
153+ IoCContainer . applyInjections ( ret , target ) ;
154+ return ret ;
153155 } , target ) ;
154156 }
155157 else {
156- newConstructor = InjectorHanlder . decorateConstructor ( function ( ...args : any [ ] ) {
158+ newConstructor = InjectorHanlder . decorateConstructor ( function ioc_wrapper ( ...args : any [ ] ) {
157159 IoCContainer . assertInstantiable ( target ) ;
158- IoCContainer . applyInjections ( this , target ) ;
159- target . apply ( this , args ) ;
160+ let ret = construct ( target , args , ioc_wrapper ) ;
161+ IoCContainer . applyInjections ( ret , target ) ;
162+ return ret ;
160163 } , target ) ;
161164 }
162165 let config : ConfigImpl = < ConfigImpl > IoCContainer . bind ( target )
@@ -533,11 +536,11 @@ class InjectorHanlder {
533536
534537 static getConstructorFromType ( target : Function ) : FunctionConstructor {
535538 let typeConstructor : Function = target ;
536- if ( typeConstructor [ 'name' ] ) {
539+ if ( typeConstructor [ 'name' ] && typeConstructor [ 'name' ] !== 'ioc_wrapper' ) {
537540 return < FunctionConstructor > typeConstructor ;
538541 }
539542 while ( typeConstructor = typeConstructor [ '__parent' ] ) {
540- if ( typeConstructor [ 'name' ] ) {
543+ if ( typeConstructor [ 'name' ] && typeConstructor [ 'name' ] !== 'ioc_wrapper' ) {
541544 return < FunctionConstructor > typeConstructor ;
542545 }
543546 }
@@ -568,6 +571,7 @@ class InjectorHanlder {
568571 }
569572}
570573
574+ // For compatibility with ES5
571575interface Map < K , V > {
572576 clear ( ) : void ;
573577 delete ( key : K ) : boolean ;
@@ -584,3 +588,62 @@ interface MapConstructor {
584588 readonly prototype : Map < any , any > ;
585589}
586590declare var Map : MapConstructor ;
591+
592+ // Polyfill for Reflect.construct. Thanks to https://github.com/Mr0grog/newless
593+ function isSyntaxSupported ( example ) {
594+ try { return ! ! Function ( "" , "'use strict';" + example ) ; }
595+ catch ( error ) { return false ; }
596+ }
597+
598+ construct = global [ 'Reflect' ] && global [ 'Reflect' ] . construct || ( function ( ) {
599+ if ( isSyntaxSupported ( "class Test {}" ) ) {
600+ // The spread operator is *dramatically faster, so use it if we can:
601+ // http://jsperf.com/new-via-spread-vs-dynamic-function/4
602+ var supportsSpread = isSyntaxSupported ( "Object(...[{}])" ) ;
603+
604+ return Function ( "constructor, args, target" ,
605+ "'use strict';" +
606+ "target = target || constructor;" +
607+
608+ // extend target so the right prototype is constructed (or nearly the
609+ // right one; ideally we'd do instantiator.prototype = target.prototype,
610+ // but a class's prototype property is not writable)
611+ "class instantiator extends target {};" +
612+ // but ensure the *logic* is `constructor` for ES2015-compliant engines
613+ "Object.setPrototypeOf(instantiator, constructor);" +
614+ // ...and for Safari 9
615+ "instantiator.prototype.constructor = constructor;" +
616+
617+ ( supportsSpread ?
618+ "var value = new instantiator(...([].slice.call(args)));" :
619+
620+ // otherwise, create a dynamic function in order to use `new`
621+ // Note using `function.bind` would be simpler, but is much slower:
622+ // http://jsperf.com/new-operator-with-dynamic-function-vs-bind
623+ "var argList = '';" +
624+ "for (var i = 0, len = args.length; i < len; i++) {" +
625+ "if (i > 0) argList += ',';" +
626+ "argList += 'args[' + i + ']';" +
627+ "}" +
628+ "var constructCall = Function('constructor, args'," +
629+ "'return new constructor(' + argList + ');'" +
630+ ");" +
631+ "var value = constructCall(constructor, args);"
632+ ) +
633+
634+ // fix up the prototype so it matches the intended one, not one who's
635+ // prototype is the intended one :P
636+ "Object.setPrototypeOf(value, target.prototype);" +
637+ "return value;"
638+ ) ;
639+ }
640+ else {
641+ var instantiator = function ( ) { } ;
642+ return function construct ( constructor , args , target ) {
643+ instantiator . prototype = ( target || constructor ) . prototype ;
644+ var instance = new instantiator ( ) ;
645+ var value = constructor . apply ( instance , args ) ;
646+ return ( typeof value === "object" && value ) || instance ;
647+ }
648+ }
649+ } ) ( ) ;
0 commit comments