1- import { FIELD , isPresent , isBlank , Type , int } from 'facade/lang' ;
1+ import { FIELD , isPresent , isBlank , Type , int , BaseException } from 'facade/lang' ;
22import { Math } from 'facade/math' ;
33import { List , ListWrapper } from 'facade/collection' ;
44import { Injector , Key , Dependency , bind , Binding , NoProviderError , ProviderError , CyclicDependencyError } from 'di/di' ;
@@ -106,6 +106,7 @@ export class ProtoElementInjector {
106106 @FIELD ( '_binding7:Binding' )
107107 @FIELD ( '_binding8:Binding' )
108108 @FIELD ( '_binding9:Binding' )
109+ @FIELD ( '_binding0IsComponent:int' )
109110 @FIELD ( '_key0:int' )
110111 @FIELD ( '_key1:int' )
111112 @FIELD ( '_key2:int' )
@@ -118,10 +119,11 @@ export class ProtoElementInjector {
118119 @FIELD ( '_key9:int' )
119120 @FIELD ( 'final parent:ProtoElementInjector' )
120121 @FIELD ( 'final index:int' )
121- constructor ( parent :ProtoElementInjector , index :int , bindings :List ) {
122+ constructor ( parent :ProtoElementInjector , index :int , bindings :List , firstBindingIsComponent : boolean = false ) {
122123 this . parent = parent ;
123124 this . index = index ;
124125
126+ this . _binding0IsComponent = firstBindingIsComponent ;
125127 this . _binding0 = null ; this . _keyId0 = null ;
126128 this . _binding1 = null ; this . _keyId1 = null ;
127129 this . _binding2 = null ; this . _keyId2 = null ;
@@ -150,8 +152,8 @@ export class ProtoElementInjector {
150152 }
151153 }
152154
153- instantiate ( parent :ElementInjector , view ) :ElementInjector {
154- return new ElementInjector ( this , parent , view ) ;
155+ instantiate ( parent :ElementInjector , host : ElementInjector , view ) :ElementInjector {
156+ return new ElementInjector ( this , parent , host , view ) ;
155157 }
156158
157159 _createBinding ( bindingOrType ) {
@@ -212,7 +214,9 @@ export class ElementInjector extends TreeNode {
212214 */
213215
214216 @FIELD ( '_proto:ProtoElementInjector' )
215- @FIELD ( '_appInjector:Injector' )
217+ @FIELD ( '_lightDomAppInjector:Injector' )
218+ @FIELD ( '_shadowDomAppInjector:Injector' )
219+ @FIELD ( '_host:ElementInjector' )
216220 @FIELD ( '_obj0:Object' )
217221 @FIELD ( '_obj1:Object' )
218222 @FIELD ( '_obj2:Object' )
@@ -224,13 +228,24 @@ export class ElementInjector extends TreeNode {
224228 @FIELD ( '_obj8:Object' )
225229 @FIELD ( '_obj9:Object' )
226230 @FIELD ( '_view:View' )
227- constructor ( proto :ProtoElementInjector , parent :ElementInjector , view ) {
231+ constructor ( proto :ProtoElementInjector , parent :ElementInjector , host : ElementInjector , view ) {
228232 super ( parent ) ;
233+ if ( isPresent ( parent ) && isPresent ( host ) ) {
234+ throw new BaseException ( 'Only either parent or host is allowed' ) ;
235+ }
236+ this . _host = null ; // needed to satisfy Dart
237+ if ( isPresent ( parent ) ) {
238+ this . _host = parent . _host ;
239+ } else {
240+ this . _host = host ;
241+ }
242+
229243 this . _proto = proto ;
230244 this . _view = view ;
231245
232246 //we cannot call clearDirectives because fields won't be detected
233- this . _appInjector = null ;
247+ this . _lightDomAppInjector = null ;
248+ this . _shadowDomAppInjector = null ;
234249 this . _obj0 = null ;
235250 this . _obj1 = null ;
236251 this . _obj2 = null ;
@@ -245,7 +260,9 @@ export class ElementInjector extends TreeNode {
245260 }
246261
247262 clearDirectives ( ) {
248- this . _appInjector = null ;
263+ this . _lightDomAppInjector = null ;
264+ this . _shadowDomAppInjector = null ;
265+
249266 this . _obj0 = null ;
250267 this . _obj1 = null ;
251268 this . _obj2 = null ;
@@ -259,24 +276,42 @@ export class ElementInjector extends TreeNode {
259276 this . _constructionCounter = 0 ;
260277 }
261278
262- instantiateDirectives ( appInjector :Injector ) {
263- this . _appInjector = appInjector ;
264-
279+ instantiateDirectives ( lightDomAppInjector :Injector , shadowDomAppInjector :Injector ) {
265280 var p = this . _proto ;
281+ if ( this . _proto . _binding0IsComponent && isBlank ( shadowDomAppInjector ) ) {
282+ throw new BaseException ( 'A shadowDomAppInjector is required as this ElementInjector contains a component' ) ;
283+ } else if ( ! this . _proto . _binding0IsComponent && isPresent ( shadowDomAppInjector ) ) {
284+ throw new BaseException ( 'No shadowDomAppInjector allowed as there is not component stored in this ElementInjector' ) ;
285+ }
286+ this . _lightDomAppInjector = lightDomAppInjector ;
287+ this . _shadowDomAppInjector = shadowDomAppInjector ;
288+
266289 if ( isPresent ( p . _keyId0 ) ) this . _getDirectiveByKeyId ( p . _keyId0 ) ;
267290 if ( isPresent ( p . _keyId1 ) ) this . _getDirectiveByKeyId ( p . _keyId1 ) ;
268- if ( isPresent ( p . _keyId2 ) ) this . _getDirectiveByKeyId ( p . _keyId2 ) ; ;
269- if ( isPresent ( p . _keyId3 ) ) this . _getDirectiveByKeyId ( p . _keyId3 ) ; ;
270- if ( isPresent ( p . _keyId4 ) ) this . _getDirectiveByKeyId ( p . _keyId4 ) ; ;
271- if ( isPresent ( p . _keyId5 ) ) this . _getDirectiveByKeyId ( p . _keyId5 ) ; ;
272- if ( isPresent ( p . _keyId6 ) ) this . _getDirectiveByKeyId ( p . _keyId6 ) ; ;
273- if ( isPresent ( p . _keyId7 ) ) this . _getDirectiveByKeyId ( p . _keyId7 ) ; ;
274- if ( isPresent ( p . _keyId8 ) ) this . _getDirectiveByKeyId ( p . _keyId8 ) ; ;
275- if ( isPresent ( p . _keyId9 ) ) this . _getDirectiveByKeyId ( p . _keyId9 ) ; ;
291+ if ( isPresent ( p . _keyId2 ) ) this . _getDirectiveByKeyId ( p . _keyId2 ) ;
292+ if ( isPresent ( p . _keyId3 ) ) this . _getDirectiveByKeyId ( p . _keyId3 ) ;
293+ if ( isPresent ( p . _keyId4 ) ) this . _getDirectiveByKeyId ( p . _keyId4 ) ;
294+ if ( isPresent ( p . _keyId5 ) ) this . _getDirectiveByKeyId ( p . _keyId5 ) ;
295+ if ( isPresent ( p . _keyId6 ) ) this . _getDirectiveByKeyId ( p . _keyId6 ) ;
296+ if ( isPresent ( p . _keyId7 ) ) this . _getDirectiveByKeyId ( p . _keyId7 ) ;
297+ if ( isPresent ( p . _keyId8 ) ) this . _getDirectiveByKeyId ( p . _keyId8 ) ;
298+ if ( isPresent ( p . _keyId9 ) ) this . _getDirectiveByKeyId ( p . _keyId9 ) ;
276299 }
277300
278301 get ( token ) {
279- return this . _getByKey ( Key . get ( token ) , 0 ) ;
302+ return this . _getByKey ( Key . get ( token ) , 0 , null ) ;
303+ }
304+
305+ getComponent ( ) {
306+ if ( this . _proto . _binding0IsComponent ) {
307+ return this . _obj0 ;
308+ } else {
309+ throw new BaseException ( 'There is not component stored in this ElementInjector' ) ;
310+ }
311+ }
312+
313+ _isComponentKey ( key :Key ) {
314+ return this . _proto . _binding0IsComponent && key . id === this . _proto . _keyId0 ;
280315 }
281316
282317 _new ( binding :Binding ) {
@@ -290,16 +325,16 @@ export class ElementInjector extends TreeNode {
290325
291326 var d0 , d1 , d2 , d3 , d4 , d5 , d6 , d7 , d8 , d9 ;
292327 try {
293- d0 = length > 0 ? this . _getByDependency ( deps [ 0 ] ) : null ;
294- d1 = length > 1 ? this . _getByDependency ( deps [ 1 ] ) : null ;
295- d2 = length > 2 ? this . _getByDependency ( deps [ 2 ] ) : null ;
296- d3 = length > 3 ? this . _getByDependency ( deps [ 3 ] ) : null ;
297- d4 = length > 4 ? this . _getByDependency ( deps [ 4 ] ) : null ;
298- d5 = length > 5 ? this . _getByDependency ( deps [ 5 ] ) : null ;
299- d6 = length > 6 ? this . _getByDependency ( deps [ 6 ] ) : null ;
300- d7 = length > 7 ? this . _getByDependency ( deps [ 7 ] ) : null ;
301- d8 = length > 8 ? this . _getByDependency ( deps [ 8 ] ) : null ;
302- d9 = length > 9 ? this . _getByDependency ( deps [ 9 ] ) : null ;
328+ d0 = length > 0 ? this . _getByDependency ( deps [ 0 ] , binding . key ) : null ;
329+ d1 = length > 1 ? this . _getByDependency ( deps [ 1 ] , binding . key ) : null ;
330+ d2 = length > 2 ? this . _getByDependency ( deps [ 2 ] , binding . key ) : null ;
331+ d3 = length > 3 ? this . _getByDependency ( deps [ 3 ] , binding . key ) : null ;
332+ d4 = length > 4 ? this . _getByDependency ( deps [ 4 ] , binding . key ) : null ;
333+ d5 = length > 5 ? this . _getByDependency ( deps [ 5 ] , binding . key ) : null ;
334+ d6 = length > 6 ? this . _getByDependency ( deps [ 6 ] , binding . key ) : null ;
335+ d7 = length > 7 ? this . _getByDependency ( deps [ 7 ] , binding . key ) : null ;
336+ d8 = length > 8 ? this . _getByDependency ( deps [ 8 ] , binding . key ) : null ;
337+ d9 = length > 9 ? this . _getByDependency ( deps [ 9 ] , binding . key ) : null ;
303338 } catch ( e ) {
304339 if ( e instanceof ProviderError ) e . addKey ( binding . key ) ;
305340 throw e ;
@@ -324,8 +359,8 @@ export class ElementInjector extends TreeNode {
324359 return obj ;
325360 }
326361
327- _getByDependency ( dep :DirectiveDependency ) {
328- return this . _getByKey ( dep . key , dep . depth ) ;
362+ _getByDependency ( dep :DirectiveDependency , requestor : Key ) {
363+ return this . _getByKey ( dep . key , dep . depth , requestor ) ;
329364 }
330365
331366 /*
@@ -340,7 +375,7 @@ export class ElementInjector extends TreeNode {
340375 *
341376 * Write benchmarks before doing this optimization.
342377 */
343- _getByKey ( key :Key , depth :int ) {
378+ _getByKey ( key :Key , depth :int , requestor : Key ) {
344379 var ei = this ;
345380 while ( ei != null && depth >= 0 ) {
346381 var specObj = ei . _getSpecialObjectByKeyId ( key . id ) ;
@@ -352,7 +387,17 @@ export class ElementInjector extends TreeNode {
352387 ei = ei . _parent ;
353388 depth -= 1 ;
354389 }
355- return this . _appInjector . get ( key ) ;
390+ if ( isPresent ( this . _host ) && this . _host . _isComponentKey ( key ) ) {
391+ return this . _host . getComponent ( ) ;
392+ } else {
393+ var appInjector ;
394+ if ( isPresent ( requestor ) && this . _isComponentKey ( requestor ) ) {
395+ appInjector = this . _shadowDomAppInjector ;
396+ } else {
397+ appInjector = this . _lightDomAppInjector ;
398+ }
399+ return appInjector . get ( key ) ;
400+ }
356401 }
357402
358403 _getSpecialObjectByKeyId ( keyId :int ) {
@@ -364,6 +409,7 @@ export class ElementInjector extends TreeNode {
364409
365410 _getDirectiveByKeyId ( keyId :int ) {
366411 var p = this . _proto ;
412+
367413 if ( p . _keyId0 === keyId ) { if ( isBlank ( this . _obj0 ) ) { this . _obj0 = this . _new ( p . _binding0 ) ; } return this . _obj0 ; }
368414 if ( p . _keyId1 === keyId ) { if ( isBlank ( this . _obj1 ) ) { this . _obj1 = this . _new ( p . _binding1 ) ; } return this . _obj1 ; }
369415 if ( p . _keyId2 === keyId ) { if ( isBlank ( this . _obj2 ) ) { this . _obj2 = this . _new ( p . _binding2 ) ; } return this . _obj2 ; }
0 commit comments