@@ -74,7 +74,7 @@ function stringifyFn(fn) {
74
74
// Support: Chrome 50-51 only
75
75
// Creating a new string by adding `' '` at the end, to hack around some bug in Chrome v50/51
76
76
// (See https://github.com/angular/angular.js/issues/14487.)
77
- // TODO (gkalpak): Remove workaround when Chrome v52 is released
77
+ // TODO(gkalpak): Remove workaround when Chrome v52 is released
78
78
return Function . prototype . toString . call ( fn ) + ' ' ;
79
79
}
80
80
@@ -129,6 +129,10 @@ function annotate(fn, strictDi, name) {
129
129
return $inject ;
130
130
}
131
131
132
+ function stringifyServiceId ( id , suffix ) {
133
+ return ( isUndefined ( id ) || isString ( id ) ) ? id : id + suffix ;
134
+ }
135
+
132
136
///////////////////////////////////////
133
137
134
138
/**
@@ -650,34 +654,34 @@ function createInjector(modulesToLoad, strictDi) {
650
654
var INSTANTIATING = { } ,
651
655
providerSuffix = 'Provider' ,
652
656
path = [ ] ,
653
- loadedModules = new HashMap ( [ ] , true ) ,
654
- providerCache = {
657
+ loadedModules = new HashMap ( null , true ) ,
658
+ providerCache = new HashMap ( {
655
659
$provide : {
656
- provider : supportObject ( provider ) ,
657
- factory : supportObject ( factory ) ,
658
- service : supportObject ( service ) ,
659
- value : supportObject ( value ) ,
660
- constant : supportObject ( constant ) ,
661
- decorator : decorator
662
- }
663
- } ,
664
- providerInjector = ( providerCache . $injector =
665
- createInternalInjector ( providerCache , function ( serviceName , caller ) {
666
- if ( angular . isString ( caller ) ) {
667
- path . push ( caller ) ;
668
- }
660
+ provider : supportObject ( provider ) ,
661
+ factory : supportObject ( factory ) ,
662
+ service : supportObject ( service ) ,
663
+ value : supportObject ( value ) ,
664
+ constant : supportObject ( constant ) ,
665
+ decorator : decorator
666
+ }
667
+ } , true ) ,
668
+ instanceCache = new HashMap ( null , true ) ,
669
+ providerInjector =
670
+ createInternalInjector ( providerCache , function ( serviceName ) {
669
671
throw $injectorMinErr ( 'unpr' , "Unknown provider: {0}" , path . join ( ' <- ' ) ) ;
670
- } ) ) ,
671
- instanceCache = { } ,
672
+ } , ' (provider)' ) ,
672
673
protoInstanceInjector =
673
- createInternalInjector ( instanceCache , function ( serviceName , caller ) {
674
- var provider = providerInjector . get ( serviceName + providerSuffix , caller ) ;
675
- return instanceInjector . invoke (
676
- provider . $get , provider , undefined , serviceName ) ;
674
+ createInternalInjector ( instanceCache , function ( serviceName ) {
675
+ var providerId = ! isString ( serviceName ) ? serviceName : serviceName + providerSuffix ;
676
+ var provider = providerInjector . get ( providerId ) ;
677
+
678
+ return instanceInjector . invoke ( provider . $get , provider , undefined , serviceName ) ;
677
679
} ) ,
678
680
instanceInjector = protoInstanceInjector ;
679
681
680
- providerCache [ '$injector' + providerSuffix ] = { $get : valueFn ( protoInstanceInjector ) } ;
682
+ providerCache . put ( '$injector' , providerInjector ) ;
683
+ providerCache . put ( '$injector' + providerSuffix , { $get : valueFn ( protoInstanceInjector ) } ) ;
684
+
681
685
var runBlocks = loadModules ( modulesToLoad ) ;
682
686
instanceInjector = protoInstanceInjector . get ( '$injector' ) ;
683
687
instanceInjector . strictDi = strictDi ;
@@ -691,7 +695,7 @@ function createInjector(modulesToLoad, strictDi) {
691
695
692
696
function supportObject ( delegate ) {
693
697
return function ( key , value ) {
694
- if ( isObject ( key ) ) {
698
+ if ( ( arguments . length === 1 ) && isObject ( key ) ) {
695
699
forEach ( key , reverseParams ( delegate ) ) ;
696
700
} else {
697
701
return delegate ( key , value ) ;
@@ -707,7 +711,11 @@ function createInjector(modulesToLoad, strictDi) {
707
711
if ( ! provider_ . $get ) {
708
712
throw $injectorMinErr ( 'pget' , "Provider '{0}' must define $get factory method." , name ) ;
709
713
}
710
- return providerCache [ name + providerSuffix ] = provider_ ;
714
+
715
+ var providerId = ! isString ( name ) ? name : name + providerSuffix ;
716
+ providerCache . put ( providerId , provider_ ) ;
717
+
718
+ return provider_ ;
711
719
}
712
720
713
721
function enforceReturnValue ( name , factory ) {
@@ -727,21 +735,24 @@ function createInjector(modulesToLoad, strictDi) {
727
735
}
728
736
729
737
function service ( name , constructor ) {
730
- return factory ( name , [ '$injector' , function ( $injector ) {
731
- return $injector . instantiate ( constructor ) ;
732
- } ] ) ;
738
+ return factory ( name , function ( ) {
739
+ return instanceInjector . instantiate ( constructor ) ;
740
+ } ) ;
733
741
}
734
742
735
- function value ( name , val ) { return factory ( name , valueFn ( val ) , false ) ; }
743
+ function value ( name , val ) {
744
+ return factory ( name , valueFn ( val ) , false ) ;
745
+ }
736
746
737
747
function constant ( name , value ) {
738
748
assertNotHasOwnProperty ( name , 'constant' ) ;
739
- providerCache [ name ] = value ;
740
- instanceCache [ name ] = value ;
749
+ providerCache . put ( name , value ) ;
750
+ instanceCache . put ( name , value ) ;
741
751
}
742
752
743
753
function decorator ( serviceName , decorFn ) {
744
- var origProvider = providerInjector . get ( serviceName + providerSuffix ) ,
754
+ var providerId = ! isString ( serviceName ) ? serviceName : serviceName + providerSuffix ;
755
+ var origProvider = providerInjector . get ( providerId ) ,
745
756
orig$get = origProvider . $get ;
746
757
747
758
origProvider . $get = function ( ) {
@@ -776,9 +787,7 @@ function createInjector(modulesToLoad, strictDi) {
776
787
runBlocks = runBlocks . concat ( loadModules ( moduleFn . requires ) ) . concat ( moduleFn . _runBlocks ) ;
777
788
runInvokeQueue ( moduleFn . _invokeQueue ) ;
778
789
runInvokeQueue ( moduleFn . _configBlocks ) ;
779
- } else if ( isFunction ( module ) ) {
780
- runBlocks . push ( providerInjector . invoke ( module ) ) ;
781
- } else if ( isArray ( module ) ) {
790
+ } else if ( isFunction ( module ) || isArray ( module ) ) {
782
791
runBlocks . push ( providerInjector . invoke ( module ) ) ;
783
792
} else {
784
793
assertArgFn ( module , 'module' ) ;
@@ -806,28 +815,44 @@ function createInjector(modulesToLoad, strictDi) {
806
815
// internal Injector
807
816
////////////////////////////////////
808
817
809
- function createInternalInjector ( cache , factory ) {
818
+ function createInternalInjector ( cache , factory , suffix ) {
819
+ suffix = suffix || '' ;
810
820
811
821
function getService ( serviceName , caller ) {
812
- if ( cache . hasOwnProperty ( serviceName ) ) {
813
- if ( cache [ serviceName ] === INSTANTIATING ) {
814
- throw $injectorMinErr ( 'cdep' , 'Circular dependency found: {0}' ,
815
- serviceName + ' <- ' + path . join ( ' <- ' ) ) ;
816
- }
817
- return cache [ serviceName ] ;
818
- } else {
819
- try {
820
- path . unshift ( serviceName ) ;
821
- cache [ serviceName ] = INSTANTIATING ;
822
- return cache [ serviceName ] = factory ( serviceName , caller ) ;
823
- } catch ( err ) {
824
- if ( cache [ serviceName ] === INSTANTIATING ) {
825
- delete cache [ serviceName ] ;
822
+ var instance ;
823
+ var callerStr = stringifyServiceId ( caller , suffix ) ;
824
+ var hasCaller = callerStr && ( path [ 0 ] !== callerStr ) ;
825
+
826
+ if ( hasCaller ) path . unshift ( callerStr ) ;
827
+ path . unshift ( stringifyServiceId ( serviceName , suffix ) ) ;
828
+
829
+ try {
830
+ if ( cache . has ( serviceName ) ) {
831
+ instance = cache . get ( serviceName ) ;
832
+
833
+ if ( instance === INSTANTIATING ) {
834
+ throw $injectorMinErr ( 'cdep' , 'Circular dependency found: {0}' , path . join ( ' <- ' ) ) ;
835
+ }
836
+
837
+ return instance ;
838
+ } else {
839
+ try {
840
+ cache . put ( serviceName , INSTANTIATING ) ;
841
+
842
+ instance = factory ( serviceName ) ;
843
+ cache . put ( serviceName , instance ) ;
844
+
845
+ return instance ;
846
+ } catch ( err ) {
847
+ if ( cache . get ( serviceName ) === INSTANTIATING ) {
848
+ cache . remove ( serviceName ) ;
849
+ }
850
+ throw err ;
826
851
}
827
- throw err ;
828
- } finally {
829
- path . shift ( ) ;
830
852
}
853
+ } finally {
854
+ path . shift ( ) ;
855
+ if ( hasCaller ) path . shift ( ) ;
831
856
}
832
857
}
833
858
@@ -838,12 +863,13 @@ function createInjector(modulesToLoad, strictDi) {
838
863
839
864
for ( var i = 0 , length = $inject . length ; i < length ; i ++ ) {
840
865
var key = $inject [ i ] ;
841
- if ( typeof key !== 'string' ) {
842
- throw $injectorMinErr ( 'itkn' ,
843
- 'Incorrect injection token! Expected service name as string, got {0}' , key ) ;
844
- }
845
- args . push ( locals && locals . hasOwnProperty ( key ) ? locals [ key ] :
846
- getService ( key , serviceName ) ) ;
866
+ // TODO(gkalpak): Remove this and the corresponding error (?)
867
+ // if (typeof key !== 'string') {
868
+ // throw $injectorMinErr('itkn',
869
+ // 'Incorrect injection token! Expected service name as string, got {0}', key);
870
+ // }
871
+ var localsHasKey = locals && isString ( key ) && locals . hasOwnProperty ( key ) ;
872
+ args . push ( localsHasKey ? locals [ key ] : getService ( key , serviceName ) ) ;
847
873
}
848
874
return args ;
849
875
}
@@ -901,7 +927,8 @@ function createInjector(modulesToLoad, strictDi) {
901
927
get : getService ,
902
928
annotate : createInjector . $$annotate ,
903
929
has : function ( name ) {
904
- return providerCache . hasOwnProperty ( name + providerSuffix ) || cache . hasOwnProperty ( name ) ;
930
+ return cache . has ( name ) ||
931
+ providerCache . has ( ! isString ( name ) ? name : name + providerSuffix ) ;
905
932
}
906
933
} ;
907
934
}
0 commit comments