11import { FIELD , isPresent , isBlank , Type , int } from 'facade/lang' ;
22import { Math } from 'facade/math' ;
33import { List , ListWrapper } from 'facade/collection' ;
4- import { Injector , Key , Dependency , bind , Binding , NoProviderError , ProviderError } from 'di/di' ;
4+ import { Injector , Key , Dependency , bind , Binding , NoProviderError , ProviderError , CyclicDependencyError } from 'di/di' ;
55import { Parent , Ancestor } from 'core/annotations/visibility' ;
66import { StaticKeys } from './static_keys' ;
77
8+ var _MAX_DIRECTIVE_CONSTRUCTION_COUNTER = 10 ;
9+
810var MAX_DEPTH = Math . pow ( 2 , 30 ) - 1 ;
11+
912var _undefined = new Object ( ) ;
1013
1114class TreeNode {
@@ -284,6 +287,7 @@ export class ElementInjector extends TreeNode {
284287 this . _obj7 = null ;
285288 this . _obj8 = null ;
286289 this . _obj9 = null ;
290+ this . _constructionCounter = 0 ;
287291 }
288292
289293 clearDirectives ( ) {
@@ -298,29 +302,34 @@ export class ElementInjector extends TreeNode {
298302 this . _obj7 = null ;
299303 this . _obj8 = null ;
300304 this . _obj9 = null ;
305+ this . _constructionCounter = 0 ;
301306 }
302307
303308 instantiateDirectives ( appInjector :Injector ) {
304309 this . _appInjector = appInjector ;
305310
306311 var p = this . _proto ;
307- if ( isPresent ( p . _keyId0 ) ) this . _obj0 = this . _new ( p . _binding0 ) ;
308- if ( isPresent ( p . _keyId1 ) ) this . _obj1 = this . _new ( p . _binding1 ) ;
309- if ( isPresent ( p . _keyId2 ) ) this . _obj2 = this . _new ( p . _binding2 ) ;
310- if ( isPresent ( p . _keyId3 ) ) this . _obj3 = this . _new ( p . _binding3 ) ;
311- if ( isPresent ( p . _keyId4 ) ) this . _obj4 = this . _new ( p . _binding4 ) ;
312- if ( isPresent ( p . _keyId5 ) ) this . _obj5 = this . _new ( p . _binding5 ) ;
313- if ( isPresent ( p . _keyId6 ) ) this . _obj6 = this . _new ( p . _binding6 ) ;
314- if ( isPresent ( p . _keyId7 ) ) this . _obj7 = this . _new ( p . _binding7 ) ;
315- if ( isPresent ( p . _keyId8 ) ) this . _obj8 = this . _new ( p . _binding8 ) ;
316- if ( isPresent ( p . _keyId9 ) ) this . _obj9 = this . _new ( p . _binding9 ) ;
312+ if ( isPresent ( p . _keyId0 ) ) this . _getDirectiveByKeyId ( p . _keyId0 ) ;
313+ if ( isPresent ( p . _keyId1 ) ) this . _getDirectiveByKeyId ( p . _keyId1 ) ;
314+ if ( isPresent ( p . _keyId2 ) ) this . _getDirectiveByKeyId ( p . _keyId2 ) ; ;
315+ if ( isPresent ( p . _keyId3 ) ) this . _getDirectiveByKeyId ( p . _keyId3 ) ; ;
316+ if ( isPresent ( p . _keyId4 ) ) this . _getDirectiveByKeyId ( p . _keyId4 ) ; ;
317+ if ( isPresent ( p . _keyId5 ) ) this . _getDirectiveByKeyId ( p . _keyId5 ) ; ;
318+ if ( isPresent ( p . _keyId6 ) ) this . _getDirectiveByKeyId ( p . _keyId6 ) ; ;
319+ if ( isPresent ( p . _keyId7 ) ) this . _getDirectiveByKeyId ( p . _keyId7 ) ; ;
320+ if ( isPresent ( p . _keyId8 ) ) this . _getDirectiveByKeyId ( p . _keyId8 ) ; ;
321+ if ( isPresent ( p . _keyId9 ) ) this . _getDirectiveByKeyId ( p . _keyId9 ) ; ;
317322 }
318323
319324 get ( token ) {
320325 return this . _getByKey ( Key . get ( token ) , 0 ) ;
321326 }
322327
323328 _new ( binding :Binding ) {
329+ if ( this . _constructionCounter ++ > _MAX_DIRECTIVE_CONSTRUCTION_COUNTER ) {
330+ throw new CyclicDependencyError ( binding . key ) ;
331+ }
332+
324333 var factory = binding . factory ;
325334 var deps = binding . dependencies ;
326335 var length = deps . length ;
@@ -365,7 +374,6 @@ export class ElementInjector extends TreeNode {
365374 return this . _getByKey ( dep . key , dep . depth ) ;
366375 }
367376
368-
369377 /*
370378 * It is fairly easy to annotate keys with metadata.
371379 * For example, key.metadata = 'directive'.
@@ -381,10 +389,10 @@ export class ElementInjector extends TreeNode {
381389 _getByKey ( key :Key , depth :int ) {
382390 var ei = this ;
383391 while ( ei != null && depth >= 0 ) {
384- var specObj = ei . _getSpecialObjectByKey ( key ) ;
392+ var specObj = ei . _getSpecialObjectByKeyId ( key . id ) ;
385393 if ( specObj !== _undefined ) return specObj ;
386394
387- var dir = ei . _getDirectiveByKey ( key ) ;
395+ var dir = ei . _getDirectiveByKeyId ( key . id ) ;
388396 if ( dir !== _undefined ) return dir ;
389397
390398 ei = ei . _parent ;
@@ -393,28 +401,25 @@ export class ElementInjector extends TreeNode {
393401 return this . _appInjector . get ( key ) ;
394402 }
395403
396- _getSpecialObjectByKey ( key : Key ) {
404+ _getSpecialObjectByKeyId ( keyId : int ) {
397405 var staticKeys = StaticKeys . instance ( ) ;
398- var keyId = key . id ;
399-
400406 if ( keyId === staticKeys . viewId ) return this . _view ;
401407 //TODO add other objects as needed
402408 return _undefined ;
403409 }
404410
405- _getDirectiveByKey ( key : Key ) {
411+ _getDirectiveByKeyId ( keyId : int ) {
406412 var p = this . _proto ;
407- var keyId = key . id ;
408- if ( p . _keyId0 === keyId ) return this . _obj0 ;
409- if ( p . _keyId1 === keyId ) return this . _obj1 ;
410- if ( p . _keyId2 === keyId ) return this . _obj2 ;
411- if ( p . _keyId3 === keyId ) return this . _obj3 ;
412- if ( p . _keyId4 === keyId ) return this . _obj4 ;
413- if ( p . _keyId5 === keyId ) return this . _obj5 ;
414- if ( p . _keyId6 === keyId ) return this . _obj6 ;
415- if ( p . _keyId7 === keyId ) return this . _obj7 ;
416- if ( p . _keyId8 === keyId ) return this . _obj8 ;
417- if ( p . _keyId9 === keyId ) return this . _obj9 ;
413+ if ( p . _keyId0 === keyId ) { if ( isBlank ( this . _obj0 ) ) { this . _obj0 = this . _new ( p . _binding0 ) ; } return this . _obj0 ; }
414+ if ( p . _keyId1 === keyId ) { if ( isBlank ( this . _obj1 ) ) { this . _obj1 = this . _new ( p . _binding1 ) ; } return this . _obj1 ; }
415+ if ( p . _keyId2 === keyId ) { if ( isBlank ( this . _obj2 ) ) { this . _obj2 = this . _new ( p . _binding2 ) ; } return this . _obj2 ; }
416+ if ( p . _keyId3 === keyId ) { if ( isBlank ( this . _obj3 ) ) { this . _obj3 = this . _new ( p . _binding3 ) ; } return this . _obj3 ; }
417+ if ( p . _keyId4 === keyId ) { if ( isBlank ( this . _obj4 ) ) { this . _obj4 = this . _new ( p . _binding4 ) ; } return this . _obj4 ; }
418+ if ( p . _keyId5 === keyId ) { if ( isBlank ( this . _obj5 ) ) { this . _obj5 = this . _new ( p . _binding5 ) ; } return this . _obj5 ; }
419+ if ( p . _keyId6 === keyId ) { if ( isBlank ( this . _obj6 ) ) { this . _obj6 = this . _new ( p . _binding6 ) ; } return this . _obj6 ; }
420+ if ( p . _keyId7 === keyId ) { if ( isBlank ( this . _obj7 ) ) { this . _obj7 = this . _new ( p . _binding7 ) ; } return this . _obj7 ; }
421+ if ( p . _keyId8 === keyId ) { if ( isBlank ( this . _obj8 ) ) { this . _obj8 = this . _new ( p . _binding8 ) ; } return this . _obj8 ; }
422+ if ( p . _keyId9 === keyId ) { if ( isBlank ( this . _obj9 ) ) { this . _obj9 = this . _new ( p . _binding9 ) ; } return this . _obj9 ; }
418423 return _undefined ;
419424 }
420425
0 commit comments