| 
									
										
										
										
											2016-06-23 09:47:54 -07:00
										 |  |  | /** | 
					
						
							|  |  |  |  * @license | 
					
						
							|  |  |  |  * Copyright Google Inc. All Rights Reserved. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Use of this source code is governed by an MIT-style license that can be | 
					
						
							|  |  |  |  * found in the LICENSE file at https://angular.io/license
 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-10 15:55:18 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-23 09:42:19 -08:00
										 |  |  | import {CompileDiDependencyMetadata, CompileDirectiveMetadata, CompileDirectiveSummary, CompileNgModuleMetadata, CompileProviderMetadata, CompileQueryMetadata, CompileTokenMetadata, CompileTypeMetadata, tokenName, tokenReference} from './compile_metadata'; | 
					
						
							| 
									
										
										
										
											2017-05-18 13:46:51 -07:00
										 |  |  | import {CompileReflector} from './compile_reflector'; | 
					
						
							|  |  |  | import {Identifiers, createTokenForExternalReference} from './identifiers'; | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  | import {ParseError, ParseSourceSpan} from './parse_util'; | 
					
						
							| 
									
										
										
										
											2017-02-15 08:36:49 -08:00
										 |  |  | import {AttrAst, DirectiveAst, ProviderAst, ProviderAstType, QueryMatch, ReferenceAst} from './template_parser/template_ast'; | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | export class ProviderError extends ParseError { | 
					
						
							|  |  |  |   constructor(message: string, span: ParseSourceSpan) { super(span, message); } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-02 15:01:35 -08:00
										 |  |  | export interface QueryWithId { | 
					
						
							|  |  |  |   meta: CompileQueryMetadata; | 
					
						
							| 
									
										
										
										
											2017-02-15 08:36:49 -08:00
										 |  |  |   queryId: number; | 
					
						
							| 
									
										
										
										
											2017-02-02 15:01:35 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  | export class ProviderViewContext { | 
					
						
							|  |  |  |   /** | 
					
						
							|  |  |  |    * @internal | 
					
						
							|  |  |  |    */ | 
					
						
							| 
									
										
										
										
											2017-02-02 15:01:35 -08:00
										 |  |  |   viewQueries: Map<any, QueryWithId[]>; | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |   /** | 
					
						
							|  |  |  |    * @internal | 
					
						
							|  |  |  |    */ | 
					
						
							| 
									
										
										
										
											2016-08-29 08:52:25 -07:00
										 |  |  |   viewProviders: Map<any, boolean>; | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |   errors: ProviderError[] = []; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-18 13:46:51 -07:00
										 |  |  |   constructor(public reflector: CompileReflector, public component: CompileDirectiveMetadata) { | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |     this.viewQueries = _getViewQueries(component); | 
					
						
							| 
									
										
										
										
											2016-08-29 08:52:25 -07:00
										 |  |  |     this.viewProviders = new Map<any, boolean>(); | 
					
						
							| 
									
										
										
										
											2016-11-30 10:52:51 -08:00
										 |  |  |     component.viewProviders.forEach((provider) => { | 
					
						
							| 
									
										
										
										
											2017-03-02 09:37:01 -08:00
										 |  |  |       if (this.viewProviders.get(tokenReference(provider.token)) == null) { | 
					
						
							| 
									
										
										
										
											2016-11-23 09:42:19 -08:00
										 |  |  |         this.viewProviders.set(tokenReference(provider.token), true); | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |       } | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export class ProviderElementContext { | 
					
						
							| 
									
										
										
										
											2017-02-02 15:01:35 -08:00
										 |  |  |   private _contentQueries: Map<any, QueryWithId[]>; | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-29 08:52:25 -07:00
										 |  |  |   private _transformedProviders = new Map<any, ProviderAst>(); | 
					
						
							|  |  |  |   private _seenProviders = new Map<any, boolean>(); | 
					
						
							|  |  |  |   private _allProviders: Map<any, ProviderAst>; | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |   private _attrs: {[key: string]: string}; | 
					
						
							| 
									
										
										
										
											2016-04-18 13:24:42 -07:00
										 |  |  |   private _hasViewContainer: boolean = false; | 
					
						
							| 
									
										
										
										
											2017-02-02 15:01:35 -08:00
										 |  |  |   private _queriedTokens = new Map<any, QueryMatch[]>(); | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |   constructor( | 
					
						
							| 
									
										
										
										
											2016-09-23 16:37:04 -04:00
										 |  |  |       public viewContext: ProviderViewContext, private _parent: ProviderElementContext, | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |       private _isViewRoot: boolean, private _directiveAsts: DirectiveAst[], attrs: AttrAst[], | 
					
						
							| 
									
										
										
										
											2017-02-15 08:36:49 -08:00
										 |  |  |       refs: ReferenceAst[], isTemplate: boolean, contentQueryStartId: number, | 
					
						
							|  |  |  |       private _sourceSpan: ParseSourceSpan) { | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |     this._attrs = {}; | 
					
						
							|  |  |  |     attrs.forEach((attrAst) => this._attrs[attrAst.name] = attrAst.value); | 
					
						
							| 
									
										
										
										
											2016-11-12 14:08:58 +01:00
										 |  |  |     const directivesMeta = _directiveAsts.map(directiveAst => directiveAst.directive); | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |     this._allProviders = | 
					
						
							| 
									
										
										
										
											2016-09-23 16:37:04 -04:00
										 |  |  |         _resolveProvidersFromDirectives(directivesMeta, _sourceSpan, viewContext.errors); | 
					
						
							| 
									
										
										
										
											2017-02-15 08:36:49 -08:00
										 |  |  |     this._contentQueries = _getContentQueries(contentQueryStartId, directivesMeta); | 
					
						
							| 
									
										
										
										
											2016-11-03 16:58:27 -07:00
										 |  |  |     Array.from(this._allProviders.values()).forEach((provider) => { | 
					
						
							| 
									
										
										
										
											2017-02-02 15:01:35 -08:00
										 |  |  |       this._addQueryReadsTo(provider.token, provider.token, this._queriedTokens); | 
					
						
							| 
									
										
										
										
											2016-08-29 08:52:25 -07:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2017-02-15 08:36:49 -08:00
										 |  |  |     if (isTemplate) { | 
					
						
							| 
									
										
										
										
											2017-05-18 13:46:51 -07:00
										 |  |  |       const templateRefId = | 
					
						
							|  |  |  |           createTokenForExternalReference(this.viewContext.reflector, Identifiers.TemplateRef); | 
					
						
							| 
									
										
										
										
											2017-02-15 08:36:49 -08:00
										 |  |  |       this._addQueryReadsTo(templateRefId, templateRefId, this._queriedTokens); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-02-02 15:01:35 -08:00
										 |  |  |     refs.forEach((refAst) => { | 
					
						
							| 
									
										
										
										
											2017-05-18 13:46:51 -07:00
										 |  |  |       let defaultQueryValue = refAst.value || | 
					
						
							|  |  |  |           createTokenForExternalReference(this.viewContext.reflector, Identifiers.ElementRef); | 
					
						
							| 
									
										
										
										
											2017-02-02 15:01:35 -08:00
										 |  |  |       this._addQueryReadsTo({value: refAst.name}, defaultQueryValue, this._queriedTokens); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2017-05-18 13:46:51 -07:00
										 |  |  |     if (this._queriedTokens.get( | 
					
						
							|  |  |  |             this.viewContext.reflector.resolveExternalReference(Identifiers.ViewContainerRef))) { | 
					
						
							| 
									
										
										
										
											2016-04-18 13:24:42 -07:00
										 |  |  |       this._hasViewContainer = true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |     // create the providers that we know are eager first
 | 
					
						
							| 
									
										
										
										
											2016-11-03 16:58:27 -07:00
										 |  |  |     Array.from(this._allProviders.values()).forEach((provider) => { | 
					
						
							| 
									
										
										
										
											2017-02-02 15:01:35 -08:00
										 |  |  |       const eager = provider.eager || this._queriedTokens.get(tokenReference(provider.token)); | 
					
						
							| 
									
										
										
										
											2016-04-18 13:24:42 -07:00
										 |  |  |       if (eager) { | 
					
						
							|  |  |  |         this._getOrCreateLocalProvider(provider.providerType, provider.token, true); | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |       } | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   afterElement() { | 
					
						
							|  |  |  |     // collect lazy providers
 | 
					
						
							| 
									
										
										
										
											2016-11-03 16:58:27 -07:00
										 |  |  |     Array.from(this._allProviders.values()).forEach((provider) => { | 
					
						
							| 
									
										
										
										
											2016-04-18 13:24:42 -07:00
										 |  |  |       this._getOrCreateLocalProvider(provider.providerType, provider.token, false); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-03 16:58:27 -07:00
										 |  |  |   get transformProviders(): ProviderAst[] { | 
					
						
							| 
									
										
										
										
											2017-05-11 10:26:02 -07:00
										 |  |  |     // Note: Maps keep their insertion order.
 | 
					
						
							|  |  |  |     const lazyProviders: ProviderAst[] = []; | 
					
						
							|  |  |  |     const eagerProviders: ProviderAst[] = []; | 
					
						
							|  |  |  |     this._transformedProviders.forEach(provider => { | 
					
						
							|  |  |  |       if (provider.eager) { | 
					
						
							|  |  |  |         eagerProviders.push(provider); | 
					
						
							|  |  |  |       } else { | 
					
						
							|  |  |  |         lazyProviders.push(provider); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     return lazyProviders.concat(eagerProviders); | 
					
						
							| 
									
										
										
										
											2016-11-03 16:58:27 -07:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   get transformedDirectiveAsts(): DirectiveAst[] { | 
					
						
							| 
									
										
										
										
											2016-11-12 14:08:58 +01:00
										 |  |  |     const sortedProviderTypes = this.transformProviders.map(provider => provider.token.identifier); | 
					
						
							|  |  |  |     const sortedDirectives = this._directiveAsts.slice(); | 
					
						
							| 
									
										
										
										
											2016-10-21 15:14:44 -07:00
										 |  |  |     sortedDirectives.sort( | 
					
						
							|  |  |  |         (dir1, dir2) => sortedProviderTypes.indexOf(dir1.directive.type) - | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |             sortedProviderTypes.indexOf(dir2.directive.type)); | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |     return sortedDirectives; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-18 13:24:42 -07:00
										 |  |  |   get transformedHasViewContainer(): boolean { return this._hasViewContainer; } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-02 15:01:35 -08:00
										 |  |  |   get queryMatches(): QueryMatch[] { | 
					
						
							|  |  |  |     const allMatches: QueryMatch[] = []; | 
					
						
							|  |  |  |     this._queriedTokens.forEach((matches: QueryMatch[]) => { allMatches.push(...matches); }); | 
					
						
							|  |  |  |     return allMatches; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   private _addQueryReadsTo( | 
					
						
							|  |  |  |       token: CompileTokenMetadata, defaultValue: CompileTokenMetadata, | 
					
						
							|  |  |  |       queryReadTokens: Map<any, QueryMatch[]>) { | 
					
						
							| 
									
										
										
										
											2016-04-18 13:24:42 -07:00
										 |  |  |     this._getQueriesFor(token).forEach((query) => { | 
					
						
							| 
									
										
										
										
											2017-02-02 15:01:35 -08:00
										 |  |  |       const queryValue = query.meta.read || defaultValue; | 
					
						
							|  |  |  |       const tokenRef = tokenReference(queryValue); | 
					
						
							|  |  |  |       let queryMatches = queryReadTokens.get(tokenRef); | 
					
						
							|  |  |  |       if (!queryMatches) { | 
					
						
							|  |  |  |         queryMatches = []; | 
					
						
							|  |  |  |         queryReadTokens.set(tokenRef, queryMatches); | 
					
						
							| 
									
										
										
										
											2016-04-18 13:24:42 -07:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2017-02-15 08:36:49 -08:00
										 |  |  |       queryMatches.push({queryId: query.queryId, value: queryValue}); | 
					
						
							| 
									
										
										
										
											2016-04-18 13:24:42 -07:00
										 |  |  |     }); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-02 15:01:35 -08:00
										 |  |  |   private _getQueriesFor(token: CompileTokenMetadata): QueryWithId[] { | 
					
						
							|  |  |  |     const result: QueryWithId[] = []; | 
					
						
							| 
									
										
										
										
											2016-11-12 14:08:58 +01:00
										 |  |  |     let currentEl: ProviderElementContext = this; | 
					
						
							|  |  |  |     let distance = 0; | 
					
						
							| 
									
										
										
										
											2017-03-24 09:59:58 -07:00
										 |  |  |     let queries: QueryWithId[]|undefined; | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |     while (currentEl !== null) { | 
					
						
							| 
									
										
										
										
											2016-11-23 09:42:19 -08:00
										 |  |  |       queries = currentEl._contentQueries.get(tokenReference(token)); | 
					
						
							| 
									
										
										
										
											2017-01-04 13:59:43 -08:00
										 |  |  |       if (queries) { | 
					
						
							| 
									
										
										
										
											2017-02-02 15:01:35 -08:00
										 |  |  |         result.push(...queries.filter((query) => query.meta.descendants || distance <= 1)); | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |       } | 
					
						
							|  |  |  |       if (currentEl._directiveAsts.length > 0) { | 
					
						
							|  |  |  |         distance++; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       currentEl = currentEl._parent; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-11-23 09:42:19 -08:00
										 |  |  |     queries = this.viewContext.viewQueries.get(tokenReference(token)); | 
					
						
							| 
									
										
										
										
											2017-01-04 13:59:43 -08:00
										 |  |  |     if (queries) { | 
					
						
							| 
									
										
										
										
											2016-10-21 15:14:44 -07:00
										 |  |  |       result.push(...queries); | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-04-18 13:24:42 -07:00
										 |  |  |     return result; | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |   private _getOrCreateLocalProvider( | 
					
						
							|  |  |  |       requestingProviderType: ProviderAstType, token: CompileTokenMetadata, | 
					
						
							| 
									
										
										
										
											2017-03-24 09:59:58 -07:00
										 |  |  |       eager: boolean): ProviderAst|null { | 
					
						
							| 
									
										
										
										
											2016-11-23 09:42:19 -08:00
										 |  |  |     const resolvedProvider = this._allProviders.get(tokenReference(token)); | 
					
						
							| 
									
										
										
										
											2016-09-30 09:26:53 -07:00
										 |  |  |     if (!resolvedProvider || ((requestingProviderType === ProviderAstType.Directive || | 
					
						
							|  |  |  |                                requestingProviderType === ProviderAstType.PublicService) && | 
					
						
							|  |  |  |                               resolvedProvider.providerType === ProviderAstType.PrivateService) || | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |         ((requestingProviderType === ProviderAstType.PrivateService || | 
					
						
							|  |  |  |           requestingProviderType === ProviderAstType.PublicService) && | 
					
						
							|  |  |  |          resolvedProvider.providerType === ProviderAstType.Builtin)) { | 
					
						
							|  |  |  |       return null; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-11-23 09:42:19 -08:00
										 |  |  |     let transformedProviderAst = this._transformedProviders.get(tokenReference(token)); | 
					
						
							| 
									
										
										
										
											2017-01-04 13:59:43 -08:00
										 |  |  |     if (transformedProviderAst) { | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |       return transformedProviderAst; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-03-02 09:37:01 -08:00
										 |  |  |     if (this._seenProviders.get(tokenReference(token)) != null) { | 
					
						
							| 
									
										
										
										
											2016-09-23 16:37:04 -04:00
										 |  |  |       this.viewContext.errors.push(new ProviderError( | 
					
						
							| 
									
										
										
										
											2016-11-23 09:42:19 -08:00
										 |  |  |           `Cannot instantiate cyclic dependency! ${tokenName(token)}`, this._sourceSpan)); | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |       return null; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-11-23 09:42:19 -08:00
										 |  |  |     this._seenProviders.set(tokenReference(token), true); | 
					
						
							| 
									
										
										
										
											2016-11-12 14:08:58 +01:00
										 |  |  |     const transformedProviders = resolvedProvider.providers.map((provider) => { | 
					
						
							|  |  |  |       let transformedUseValue = provider.useValue; | 
					
						
							| 
									
										
										
										
											2017-03-24 09:59:58 -07:00
										 |  |  |       let transformedUseExisting = provider.useExisting !; | 
					
						
							|  |  |  |       let transformedDeps: CompileDiDependencyMetadata[] = undefined !; | 
					
						
							| 
									
										
										
										
											2017-03-02 09:37:01 -08:00
										 |  |  |       if (provider.useExisting != null) { | 
					
						
							| 
									
										
										
										
											2016-11-12 14:08:58 +01:00
										 |  |  |         const existingDiDep = this._getDependency( | 
					
						
							| 
									
										
										
										
											2017-03-24 09:59:58 -07:00
										 |  |  |             resolvedProvider.providerType, {token: provider.useExisting}, eager) !; | 
					
						
							| 
									
										
										
										
											2017-03-02 09:37:01 -08:00
										 |  |  |         if (existingDiDep.token != null) { | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |           transformedUseExisting = existingDiDep.token; | 
					
						
							|  |  |  |         } else { | 
					
						
							| 
									
										
										
										
											2017-03-24 09:59:58 -07:00
										 |  |  |           transformedUseExisting = null !; | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |           transformedUseValue = existingDiDep.value; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-01-04 13:59:43 -08:00
										 |  |  |       } else if (provider.useFactory) { | 
					
						
							| 
									
										
										
										
											2016-11-12 14:08:58 +01:00
										 |  |  |         const deps = provider.deps || provider.useFactory.diDeps; | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |         transformedDeps = | 
					
						
							| 
									
										
										
										
											2017-03-24 09:59:58 -07:00
										 |  |  |             deps.map((dep) => this._getDependency(resolvedProvider.providerType, dep, eager) !); | 
					
						
							| 
									
										
										
										
											2017-01-04 13:59:43 -08:00
										 |  |  |       } else if (provider.useClass) { | 
					
						
							| 
									
										
										
										
											2016-11-12 14:08:58 +01:00
										 |  |  |         const deps = provider.deps || provider.useClass.diDeps; | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |         transformedDeps = | 
					
						
							| 
									
										
										
										
											2017-03-24 09:59:58 -07:00
										 |  |  |             deps.map((dep) => this._getDependency(resolvedProvider.providerType, dep, eager) !); | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |       } | 
					
						
							|  |  |  |       return _transformProvider(provider, { | 
					
						
							|  |  |  |         useExisting: transformedUseExisting, | 
					
						
							|  |  |  |         useValue: transformedUseValue, | 
					
						
							|  |  |  |         deps: transformedDeps | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     transformedProviderAst = | 
					
						
							|  |  |  |         _transformProviderAst(resolvedProvider, {eager: eager, providers: transformedProviders}); | 
					
						
							| 
									
										
										
										
											2016-11-23 09:42:19 -08:00
										 |  |  |     this._transformedProviders.set(tokenReference(token), transformedProviderAst); | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |     return transformedProviderAst; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |   private _getLocalDependency( | 
					
						
							|  |  |  |       requestingProviderType: ProviderAstType, dep: CompileDiDependencyMetadata, | 
					
						
							| 
									
										
										
										
											2017-03-24 09:59:58 -07:00
										 |  |  |       eager: boolean = false): CompileDiDependencyMetadata|null { | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |     if (dep.isAttribute) { | 
					
						
							| 
									
										
										
										
											2017-03-24 09:59:58 -07:00
										 |  |  |       const attrValue = this._attrs[dep.token !.value]; | 
					
						
							| 
									
										
										
										
											2016-11-30 10:52:51 -08:00
										 |  |  |       return {isValue: true, value: attrValue == null ? null : attrValue}; | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-02 09:37:01 -08:00
										 |  |  |     if (dep.token != null) { | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |       // access builtints
 | 
					
						
							|  |  |  |       if ((requestingProviderType === ProviderAstType.Directive || | 
					
						
							|  |  |  |            requestingProviderType === ProviderAstType.Component)) { | 
					
						
							| 
									
										
										
										
											2017-05-18 13:46:51 -07:00
										 |  |  |         if (tokenReference(dep.token) === | 
					
						
							|  |  |  |                 this.viewContext.reflector.resolveExternalReference(Identifiers.Renderer) || | 
					
						
							|  |  |  |             tokenReference(dep.token) === | 
					
						
							|  |  |  |                 this.viewContext.reflector.resolveExternalReference(Identifiers.ElementRef) || | 
					
						
							|  |  |  |             tokenReference(dep.token) === | 
					
						
							|  |  |  |                 this.viewContext.reflector.resolveExternalReference( | 
					
						
							|  |  |  |                     Identifiers.ChangeDetectorRef) || | 
					
						
							|  |  |  |             tokenReference(dep.token) === | 
					
						
							|  |  |  |                 this.viewContext.reflector.resolveExternalReference(Identifiers.TemplateRef)) { | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |           return dep; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-05-18 13:46:51 -07:00
										 |  |  |         if (tokenReference(dep.token) === | 
					
						
							|  |  |  |             this.viewContext.reflector.resolveExternalReference(Identifiers.ViewContainerRef)) { | 
					
						
							| 
									
										
										
										
											2016-04-18 13:24:42 -07:00
										 |  |  |           this._hasViewContainer = true; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |       } | 
					
						
							|  |  |  |       // access the injector
 | 
					
						
							| 
									
										
										
										
											2017-05-18 13:46:51 -07:00
										 |  |  |       if (tokenReference(dep.token) === | 
					
						
							|  |  |  |           this.viewContext.reflector.resolveExternalReference(Identifiers.Injector)) { | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |         return dep; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       // access providers
 | 
					
						
							| 
									
										
										
										
											2017-03-02 09:37:01 -08:00
										 |  |  |       if (this._getOrCreateLocalProvider(requestingProviderType, dep.token, eager) != null) { | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |         return dep; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return null; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |   private _getDependency( | 
					
						
							|  |  |  |       requestingProviderType: ProviderAstType, dep: CompileDiDependencyMetadata, | 
					
						
							| 
									
										
										
										
											2017-03-24 09:59:58 -07:00
										 |  |  |       eager: boolean = false): CompileDiDependencyMetadata|null { | 
					
						
							| 
									
										
										
										
											2016-11-12 14:08:58 +01:00
										 |  |  |     let currElement: ProviderElementContext = this; | 
					
						
							|  |  |  |     let currEager: boolean = eager; | 
					
						
							| 
									
										
										
										
											2017-03-24 09:59:58 -07:00
										 |  |  |     let result: CompileDiDependencyMetadata|null = null; | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |     if (!dep.isSkipSelf) { | 
					
						
							|  |  |  |       result = this._getLocalDependency(requestingProviderType, dep, eager); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (dep.isSelf) { | 
					
						
							| 
									
										
										
										
											2016-09-30 09:26:53 -07:00
										 |  |  |       if (!result && dep.isOptional) { | 
					
						
							| 
									
										
										
										
											2016-11-30 10:52:51 -08:00
										 |  |  |         result = {isValue: true, value: null}; | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |       } | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       // check parent elements
 | 
					
						
							| 
									
										
										
										
											2017-01-04 13:59:43 -08:00
										 |  |  |       while (!result && currElement._parent) { | 
					
						
							| 
									
										
										
										
											2016-11-12 14:08:58 +01:00
										 |  |  |         const prevElement = currElement; | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |         currElement = currElement._parent; | 
					
						
							|  |  |  |         if (prevElement._isViewRoot) { | 
					
						
							|  |  |  |           currEager = false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         result = currElement._getLocalDependency(ProviderAstType.PublicService, dep, currEager); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       // check @Host restriction
 | 
					
						
							| 
									
										
										
										
											2016-09-30 09:26:53 -07:00
										 |  |  |       if (!result) { | 
					
						
							| 
									
										
										
										
											2016-11-23 09:42:19 -08:00
										 |  |  |         if (!dep.isHost || this.viewContext.component.isHost || | 
					
						
							| 
									
										
										
										
											2017-03-24 09:59:58 -07:00
										 |  |  |             this.viewContext.component.type.reference === tokenReference(dep.token !) || | 
					
						
							|  |  |  |             this.viewContext.viewProviders.get(tokenReference(dep.token !)) != null) { | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |           result = dep; | 
					
						
							|  |  |  |         } else { | 
					
						
							| 
									
										
										
										
											2016-11-30 10:52:51 -08:00
										 |  |  |           result = dep.isOptional ? result = {isValue: true, value: null} : null; | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-09-30 09:26:53 -07:00
										 |  |  |     if (!result) { | 
					
						
							| 
									
										
										
										
											2016-09-23 16:37:04 -04:00
										 |  |  |       this.viewContext.errors.push( | 
					
						
							| 
									
										
										
										
											2017-03-24 09:59:58 -07:00
										 |  |  |           new ProviderError(`No provider for ${tokenName(dep.token!)}`, this._sourceSpan)); | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |     } | 
					
						
							|  |  |  |     return result; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-28 09:54:42 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-18 03:50:31 -07:00
										 |  |  | export class NgModuleProviderAnalyzer { | 
					
						
							| 
									
										
										
										
											2016-08-29 08:52:25 -07:00
										 |  |  |   private _transformedProviders = new Map<any, ProviderAst>(); | 
					
						
							|  |  |  |   private _seenProviders = new Map<any, boolean>(); | 
					
						
							|  |  |  |   private _allProviders: Map<any, ProviderAst>; | 
					
						
							| 
									
										
										
										
											2016-06-28 09:54:42 -07:00
										 |  |  |   private _errors: ProviderError[] = []; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-18 03:50:31 -07:00
										 |  |  |   constructor( | 
					
						
							| 
									
										
										
										
											2017-05-18 13:46:51 -07:00
										 |  |  |       private reflector: CompileReflector, ngModule: CompileNgModuleMetadata, | 
					
						
							|  |  |  |       extraProviders: CompileProviderMetadata[], sourceSpan: ParseSourceSpan) { | 
					
						
							| 
									
										
										
										
											2016-08-29 08:52:25 -07:00
										 |  |  |     this._allProviders = new Map<any, ProviderAst>(); | 
					
						
							| 
									
										
										
										
											2016-11-29 08:08:22 -08:00
										 |  |  |     ngModule.transitiveModule.modules.forEach((ngModuleType: CompileTypeMetadata) => { | 
					
						
							| 
									
										
										
										
											2016-11-30 10:52:51 -08:00
										 |  |  |       const ngModuleProvider = {token: {identifier: ngModuleType}, useClass: ngModuleType}; | 
					
						
							| 
									
										
										
										
											2016-06-28 09:54:42 -07:00
										 |  |  |       _resolveProviders( | 
					
						
							| 
									
										
										
										
											2016-07-18 03:50:31 -07:00
										 |  |  |           [ngModuleProvider], ProviderAstType.PublicService, true, sourceSpan, this._errors, | 
					
						
							| 
									
										
										
										
											2016-06-28 09:54:42 -07:00
										 |  |  |           this._allProviders); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     _resolveProviders( | 
					
						
							| 
									
										
										
										
											2016-11-29 08:08:22 -08:00
										 |  |  |         ngModule.transitiveModule.providers.map(entry => entry.provider).concat(extraProviders), | 
					
						
							|  |  |  |         ProviderAstType.PublicService, false, sourceSpan, this._errors, this._allProviders); | 
					
						
							| 
									
										
										
										
											2016-06-28 09:54:42 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   parse(): ProviderAst[] { | 
					
						
							| 
									
										
										
										
											2016-11-03 16:58:27 -07:00
										 |  |  |     Array.from(this._allProviders.values()).forEach((provider) => { | 
					
						
							| 
									
										
										
										
											2016-08-29 08:52:25 -07:00
										 |  |  |       this._getOrCreateLocalProvider(provider.token, provider.eager); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2016-06-28 09:54:42 -07:00
										 |  |  |     if (this._errors.length > 0) { | 
					
						
							| 
									
										
										
										
											2016-07-13 11:01:32 -07:00
										 |  |  |       const errorString = this._errors.join('\n'); | 
					
						
							| 
									
										
										
										
											2016-08-25 00:50:16 -07:00
										 |  |  |       throw new Error(`Provider parse errors:\n${errorString}`); | 
					
						
							| 
									
										
										
										
											2016-06-28 09:54:42 -07:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-05-11 10:26:02 -07:00
										 |  |  |     // Note: Maps keep their insertion order.
 | 
					
						
							|  |  |  |     const lazyProviders: ProviderAst[] = []; | 
					
						
							|  |  |  |     const eagerProviders: ProviderAst[] = []; | 
					
						
							|  |  |  |     this._transformedProviders.forEach(provider => { | 
					
						
							|  |  |  |       if (provider.eager) { | 
					
						
							|  |  |  |         eagerProviders.push(provider); | 
					
						
							|  |  |  |       } else { | 
					
						
							|  |  |  |         lazyProviders.push(provider); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     return lazyProviders.concat(eagerProviders); | 
					
						
							| 
									
										
										
										
											2016-06-28 09:54:42 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-24 09:59:58 -07:00
										 |  |  |   private _getOrCreateLocalProvider(token: CompileTokenMetadata, eager: boolean): ProviderAst|null { | 
					
						
							| 
									
										
										
										
											2016-11-23 09:42:19 -08:00
										 |  |  |     const resolvedProvider = this._allProviders.get(tokenReference(token)); | 
					
						
							| 
									
										
										
										
											2016-09-30 09:26:53 -07:00
										 |  |  |     if (!resolvedProvider) { | 
					
						
							| 
									
										
										
										
											2016-06-28 09:54:42 -07:00
										 |  |  |       return null; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-11-23 09:42:19 -08:00
										 |  |  |     let transformedProviderAst = this._transformedProviders.get(tokenReference(token)); | 
					
						
							| 
									
										
										
										
											2017-01-04 13:59:43 -08:00
										 |  |  |     if (transformedProviderAst) { | 
					
						
							| 
									
										
										
										
											2016-06-28 09:54:42 -07:00
										 |  |  |       return transformedProviderAst; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-03-02 09:37:01 -08:00
										 |  |  |     if (this._seenProviders.get(tokenReference(token)) != null) { | 
					
						
							| 
									
										
										
										
											2016-06-28 09:54:42 -07:00
										 |  |  |       this._errors.push(new ProviderError( | 
					
						
							| 
									
										
										
										
											2016-11-23 09:42:19 -08:00
										 |  |  |           `Cannot instantiate cyclic dependency! ${tokenName(token)}`, | 
					
						
							|  |  |  |           resolvedProvider.sourceSpan)); | 
					
						
							| 
									
										
										
										
											2016-06-28 09:54:42 -07:00
										 |  |  |       return null; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-11-23 09:42:19 -08:00
										 |  |  |     this._seenProviders.set(tokenReference(token), true); | 
					
						
							| 
									
										
										
										
											2016-11-12 14:08:58 +01:00
										 |  |  |     const transformedProviders = resolvedProvider.providers.map((provider) => { | 
					
						
							|  |  |  |       let transformedUseValue = provider.useValue; | 
					
						
							| 
									
										
										
										
											2017-03-24 09:59:58 -07:00
										 |  |  |       let transformedUseExisting = provider.useExisting !; | 
					
						
							|  |  |  |       let transformedDeps: CompileDiDependencyMetadata[] = undefined !; | 
					
						
							| 
									
										
										
										
											2017-03-02 09:37:01 -08:00
										 |  |  |       if (provider.useExisting != null) { | 
					
						
							| 
									
										
										
										
											2016-11-30 10:52:51 -08:00
										 |  |  |         const existingDiDep = | 
					
						
							|  |  |  |             this._getDependency({token: provider.useExisting}, eager, resolvedProvider.sourceSpan); | 
					
						
							| 
									
										
										
										
											2017-03-02 09:37:01 -08:00
										 |  |  |         if (existingDiDep.token != null) { | 
					
						
							| 
									
										
										
										
											2016-06-28 09:54:42 -07:00
										 |  |  |           transformedUseExisting = existingDiDep.token; | 
					
						
							|  |  |  |         } else { | 
					
						
							| 
									
										
										
										
											2017-03-24 09:59:58 -07:00
										 |  |  |           transformedUseExisting = null !; | 
					
						
							| 
									
										
										
										
											2016-06-28 09:54:42 -07:00
										 |  |  |           transformedUseValue = existingDiDep.value; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-01-04 13:59:43 -08:00
										 |  |  |       } else if (provider.useFactory) { | 
					
						
							| 
									
										
										
										
											2016-11-12 14:08:58 +01:00
										 |  |  |         const deps = provider.deps || provider.useFactory.diDeps; | 
					
						
							| 
									
										
										
										
											2016-06-28 09:54:42 -07:00
										 |  |  |         transformedDeps = | 
					
						
							|  |  |  |             deps.map((dep) => this._getDependency(dep, eager, resolvedProvider.sourceSpan)); | 
					
						
							| 
									
										
										
										
											2017-01-04 13:59:43 -08:00
										 |  |  |       } else if (provider.useClass) { | 
					
						
							| 
									
										
										
										
											2016-11-12 14:08:58 +01:00
										 |  |  |         const deps = provider.deps || provider.useClass.diDeps; | 
					
						
							| 
									
										
										
										
											2016-06-28 09:54:42 -07:00
										 |  |  |         transformedDeps = | 
					
						
							|  |  |  |             deps.map((dep) => this._getDependency(dep, eager, resolvedProvider.sourceSpan)); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       return _transformProvider(provider, { | 
					
						
							|  |  |  |         useExisting: transformedUseExisting, | 
					
						
							|  |  |  |         useValue: transformedUseValue, | 
					
						
							|  |  |  |         deps: transformedDeps | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     transformedProviderAst = | 
					
						
							|  |  |  |         _transformProviderAst(resolvedProvider, {eager: eager, providers: transformedProviders}); | 
					
						
							| 
									
										
										
										
											2016-11-23 09:42:19 -08:00
										 |  |  |     this._transformedProviders.set(tokenReference(token), transformedProviderAst); | 
					
						
							| 
									
										
										
										
											2016-06-28 09:54:42 -07:00
										 |  |  |     return transformedProviderAst; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   private _getDependency( | 
					
						
							| 
									
										
										
										
											2017-03-24 09:59:58 -07:00
										 |  |  |       dep: CompileDiDependencyMetadata, eager: boolean = false, | 
					
						
							| 
									
										
										
										
											2016-06-28 09:54:42 -07:00
										 |  |  |       requestorSourceSpan: ParseSourceSpan): CompileDiDependencyMetadata { | 
					
						
							| 
									
										
										
										
											2016-11-12 14:08:58 +01:00
										 |  |  |     let foundLocal = false; | 
					
						
							| 
									
										
										
										
											2017-03-02 09:37:01 -08:00
										 |  |  |     if (!dep.isSkipSelf && dep.token != null) { | 
					
						
							| 
									
										
										
										
											2016-06-28 09:54:42 -07:00
										 |  |  |       // access the injector
 | 
					
						
							| 
									
										
										
										
											2017-05-18 13:46:51 -07:00
										 |  |  |       if (tokenReference(dep.token) === | 
					
						
							|  |  |  |               this.reflector.resolveExternalReference(Identifiers.Injector) || | 
					
						
							|  |  |  |           tokenReference(dep.token) === | 
					
						
							|  |  |  |               this.reflector.resolveExternalReference(Identifiers.ComponentFactoryResolver)) { | 
					
						
							| 
									
										
										
										
											2016-06-28 09:54:42 -07:00
										 |  |  |         foundLocal = true; | 
					
						
							|  |  |  |         // access providers
 | 
					
						
							| 
									
										
										
										
											2017-03-02 09:37:01 -08:00
										 |  |  |       } else if (this._getOrCreateLocalProvider(dep.token, eager) != null) { | 
					
						
							| 
									
										
										
										
											2016-06-28 09:54:42 -07:00
										 |  |  |         foundLocal = true; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-11-12 14:08:58 +01:00
										 |  |  |     let result: CompileDiDependencyMetadata = dep; | 
					
						
							| 
									
										
										
										
											2016-06-28 09:54:42 -07:00
										 |  |  |     if (dep.isSelf && !foundLocal) { | 
					
						
							|  |  |  |       if (dep.isOptional) { | 
					
						
							| 
									
										
										
										
											2016-11-30 10:52:51 -08:00
										 |  |  |         result = {isValue: true, value: null}; | 
					
						
							| 
									
										
										
										
											2016-06-28 09:54:42 -07:00
										 |  |  |       } else { | 
					
						
							|  |  |  |         this._errors.push( | 
					
						
							| 
									
										
										
										
											2017-03-24 09:59:58 -07:00
										 |  |  |             new ProviderError(`No provider for ${tokenName(dep.token!)}`, requestorSourceSpan)); | 
					
						
							| 
									
										
										
										
											2016-06-28 09:54:42 -07:00
										 |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return result; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  | function _transformProvider( | 
					
						
							|  |  |  |     provider: CompileProviderMetadata, | 
					
						
							|  |  |  |     {useExisting, useValue, deps}: | 
					
						
							|  |  |  |         {useExisting: CompileTokenMetadata, useValue: any, deps: CompileDiDependencyMetadata[]}) { | 
					
						
							| 
									
										
										
										
											2016-11-30 10:52:51 -08:00
										 |  |  |   return { | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |     token: provider.token, | 
					
						
							|  |  |  |     useClass: provider.useClass, | 
					
						
							|  |  |  |     useExisting: useExisting, | 
					
						
							|  |  |  |     useFactory: provider.useFactory, | 
					
						
							|  |  |  |     useValue: useValue, | 
					
						
							|  |  |  |     deps: deps, | 
					
						
							|  |  |  |     multi: provider.multi | 
					
						
							| 
									
										
										
										
											2016-11-30 10:52:51 -08:00
										 |  |  |   }; | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function _transformProviderAst( | 
					
						
							|  |  |  |     provider: ProviderAst, | 
					
						
							|  |  |  |     {eager, providers}: {eager: boolean, providers: CompileProviderMetadata[]}): ProviderAst { | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |   return new ProviderAst( | 
					
						
							|  |  |  |       provider.token, provider.multiProvider, provider.eager || eager, providers, | 
					
						
							| 
									
										
										
										
											2016-08-02 01:12:24 -07:00
										 |  |  |       provider.providerType, provider.lifecycleHooks, provider.sourceSpan); | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  | function _resolveProvidersFromDirectives( | 
					
						
							| 
									
										
										
										
											2016-11-10 16:27:53 -08:00
										 |  |  |     directives: CompileDirectiveSummary[], sourceSpan: ParseSourceSpan, | 
					
						
							| 
									
										
										
										
											2016-08-29 08:52:25 -07:00
										 |  |  |     targetErrors: ParseError[]): Map<any, ProviderAst> { | 
					
						
							| 
									
										
										
										
											2016-11-12 14:08:58 +01:00
										 |  |  |   const providersByToken = new Map<any, ProviderAst>(); | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |   directives.forEach((directive) => { | 
					
						
							| 
									
										
										
										
											2016-11-30 10:52:51 -08:00
										 |  |  |     const dirProvider: | 
					
						
							|  |  |  |         CompileProviderMetadata = {token: {identifier: directive.type}, useClass: directive.type}; | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |     _resolveProviders( | 
					
						
							|  |  |  |         [dirProvider], | 
					
						
							|  |  |  |         directive.isComponent ? ProviderAstType.Component : ProviderAstType.Directive, true, | 
					
						
							|  |  |  |         sourceSpan, targetErrors, providersByToken); | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Note: directives need to be able to overwrite providers of a component!
 | 
					
						
							| 
									
										
										
										
											2016-11-12 14:08:58 +01:00
										 |  |  |   const directivesWithComponentFirst = | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |       directives.filter(dir => dir.isComponent).concat(directives.filter(dir => !dir.isComponent)); | 
					
						
							|  |  |  |   directivesWithComponentFirst.forEach((directive) => { | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |     _resolveProviders( | 
					
						
							| 
									
										
										
										
											2016-11-30 10:52:51 -08:00
										 |  |  |         directive.providers, ProviderAstType.PublicService, false, sourceSpan, targetErrors, | 
					
						
							|  |  |  |         providersByToken); | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |     _resolveProviders( | 
					
						
							| 
									
										
										
										
											2016-11-30 10:52:51 -08:00
										 |  |  |         directive.viewProviders, ProviderAstType.PrivateService, false, sourceSpan, targetErrors, | 
					
						
							|  |  |  |         providersByToken); | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |   }); | 
					
						
							|  |  |  |   return providersByToken; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  | function _resolveProviders( | 
					
						
							|  |  |  |     providers: CompileProviderMetadata[], providerType: ProviderAstType, eager: boolean, | 
					
						
							|  |  |  |     sourceSpan: ParseSourceSpan, targetErrors: ParseError[], | 
					
						
							| 
									
										
										
										
											2016-08-29 08:52:25 -07:00
										 |  |  |     targetProvidersByToken: Map<any, ProviderAst>) { | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |   providers.forEach((provider) => { | 
					
						
							| 
									
										
										
										
											2016-11-23 09:42:19 -08:00
										 |  |  |     let resolvedProvider = targetProvidersByToken.get(tokenReference(provider.token)); | 
					
						
							| 
									
										
										
										
											2017-03-02 09:37:01 -08:00
										 |  |  |     if (resolvedProvider != null && !!resolvedProvider.multiProvider !== !!provider.multi) { | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |       targetErrors.push(new ProviderError( | 
					
						
							| 
									
										
										
										
											2016-11-23 09:42:19 -08:00
										 |  |  |           `Mixing multi and non multi provider is not possible for token ${tokenName(resolvedProvider.token)}`, | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |           sourceSpan)); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-09-30 09:26:53 -07:00
										 |  |  |     if (!resolvedProvider) { | 
					
						
							| 
									
										
										
										
											2016-11-30 10:52:51 -08:00
										 |  |  |       const lifecycleHooks = provider.token.identifier && | 
					
						
							|  |  |  |               (<CompileTypeMetadata>provider.token.identifier).lifecycleHooks ? | 
					
						
							|  |  |  |           (<CompileTypeMetadata>provider.token.identifier).lifecycleHooks : | 
					
						
							| 
									
										
										
										
											2016-08-02 01:37:42 -07:00
										 |  |  |           []; | 
					
						
							| 
									
										
										
										
											2017-03-14 14:32:26 -07:00
										 |  |  |       const isUseValue = !(provider.useClass || provider.useExisting || provider.useFactory); | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |       resolvedProvider = new ProviderAst( | 
					
						
							| 
									
										
										
										
											2017-03-24 09:59:58 -07:00
										 |  |  |           provider.token, !!provider.multi, eager || isUseValue, [provider], providerType, | 
					
						
							| 
									
										
										
										
											2017-03-14 14:32:26 -07:00
										 |  |  |           lifecycleHooks, sourceSpan); | 
					
						
							| 
									
										
										
										
											2016-11-23 09:42:19 -08:00
										 |  |  |       targetProvidersByToken.set(tokenReference(provider.token), resolvedProvider); | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |     } else { | 
					
						
							|  |  |  |       if (!provider.multi) { | 
					
						
							| 
									
										
										
										
											2016-10-21 15:14:44 -07:00
										 |  |  |         resolvedProvider.providers.length = 0; | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |       } | 
					
						
							|  |  |  |       resolvedProvider.providers.push(provider); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-02 15:01:35 -08:00
										 |  |  | function _getViewQueries(component: CompileDirectiveMetadata): Map<any, QueryWithId[]> { | 
					
						
							| 
									
										
										
										
											2017-02-15 08:36:49 -08:00
										 |  |  |   // Note: queries start with id 1 so we can use the number in a Bloom filter!
 | 
					
						
							|  |  |  |   let viewQueryId = 1; | 
					
						
							| 
									
										
										
										
											2017-02-02 15:01:35 -08:00
										 |  |  |   const viewQueries = new Map<any, QueryWithId[]>(); | 
					
						
							| 
									
										
										
										
											2017-01-04 13:59:43 -08:00
										 |  |  |   if (component.viewQueries) { | 
					
						
							| 
									
										
										
										
											2017-02-02 15:01:35 -08:00
										 |  |  |     component.viewQueries.forEach( | 
					
						
							| 
									
										
										
										
											2017-02-15 08:36:49 -08:00
										 |  |  |         (query) => _addQueryToTokenMap(viewQueries, {meta: query, queryId: viewQueryId++})); | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |   } | 
					
						
							|  |  |  |   return viewQueries; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-02 15:01:35 -08:00
										 |  |  | function _getContentQueries( | 
					
						
							| 
									
										
										
										
											2017-02-15 08:36:49 -08:00
										 |  |  |     contentQueryStartId: number, directives: CompileDirectiveSummary[]): Map<any, QueryWithId[]> { | 
					
						
							|  |  |  |   let contentQueryId = contentQueryStartId; | 
					
						
							| 
									
										
										
										
											2017-02-02 15:01:35 -08:00
										 |  |  |   const contentQueries = new Map<any, QueryWithId[]>(); | 
					
						
							|  |  |  |   directives.forEach((directive, directiveIndex) => { | 
					
						
							| 
									
										
										
										
											2017-01-04 13:59:43 -08:00
										 |  |  |     if (directive.queries) { | 
					
						
							| 
									
										
										
										
											2017-02-02 15:01:35 -08:00
										 |  |  |       directive.queries.forEach( | 
					
						
							| 
									
										
										
										
											2017-02-15 08:36:49 -08:00
										 |  |  |           (query) => _addQueryToTokenMap(contentQueries, {meta: query, queryId: contentQueryId++})); | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |     } | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  |   return contentQueries; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-02 15:01:35 -08:00
										 |  |  | function _addQueryToTokenMap(map: Map<any, QueryWithId[]>, query: QueryWithId) { | 
					
						
							|  |  |  |   query.meta.selectors.forEach((token: CompileTokenMetadata) => { | 
					
						
							| 
									
										
										
										
											2016-11-23 09:42:19 -08:00
										 |  |  |     let entry = map.get(tokenReference(token)); | 
					
						
							| 
									
										
										
										
											2016-09-30 09:26:53 -07:00
										 |  |  |     if (!entry) { | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |       entry = []; | 
					
						
							| 
									
										
										
										
											2016-11-23 09:42:19 -08:00
										 |  |  |       map.set(tokenReference(token), entry); | 
					
						
							| 
									
										
										
										
											2016-01-06 14:13:44 -08:00
										 |  |  |     } | 
					
						
							|  |  |  |     entry.push(query); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | } |