2016-06-23 12:47:54 -04: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 21:21:28 -04:00
import { AnimationAnimateMetadata , AnimationEntryMetadata , AnimationGroupMetadata , AnimationKeyframesSequenceMetadata , AnimationMetadata , AnimationStateDeclarationMetadata , AnimationStateMetadata , AnimationStateTransitionMetadata , AnimationStyleMetadata , AnimationWithStepsMetadata , AttributeMetadata , ChangeDetectionStrategy , ComponentMetadata , HostMetadata , InjectMetadata , Injectable , ModuleWithProviders , OptionalMetadata , Provider , QueryMetadata , SchemaMetadata , SelfMetadata , SkipSelfMetadata , Type , ViewQueryMetadata , resolveForwardRef } from '@angular/core' ;
2016-06-08 19:38:52 -04:00
2016-08-15 22:37:42 -04:00
import { Console , LIFECYCLE_HOOKS_VALUES , ReflectorReader , reflector } from '../core_private' ;
2016-07-21 16:56:58 -04:00
import { StringMapWrapper } from '../src/facade/collection' ;
2016-06-08 19:38:52 -04:00
2016-06-20 12:52:41 -04:00
import { assertArrayOfStrings , assertInterpolationSymbols } from './assertions' ;
2016-01-06 17:13:44 -05:00
import * as cpl from './compile_metadata' ;
2016-06-13 11:35:31 -04:00
import { CompilerConfig } from './config' ;
2016-01-06 17:13:44 -05:00
import { DirectiveResolver } from './directive_resolver' ;
2016-08-10 21:21:28 -04:00
import { BaseException } from './facade/exceptions' ;
import { isArray , isBlank , isPresent , isString , stringify } from './facade/lang' ;
2016-07-07 13:05:55 -04:00
import { Identifiers , identifierToken } from './identifiers' ;
2016-08-02 04:37:42 -04:00
import { hasLifecycleHook } from './lifecycle_reflector' ;
2016-07-18 06:50:31 -04:00
import { NgModuleResolver } from './ng_module_resolver' ;
2016-01-06 17:13:44 -05:00
import { PipeResolver } from './pipe_resolver' ;
2016-07-28 13:39:10 -04:00
import { ElementSchemaRegistry } from './schema/element_schema_registry' ;
2016-04-28 20:50:03 -04:00
import { getUrlScheme } from './url_resolver' ;
2016-06-08 19:38:52 -04:00
import { MODULE_SUFFIX , ValueTransformer , sanitizeIdentifier , visitValue } from './util' ;
2016-04-28 20:50:03 -04:00
2015-09-14 18:59:09 -04:00
@Injectable ( )
2016-02-18 13:53:21 -05:00
export class CompileMetadataResolver {
2016-08-10 21:21:28 -04:00
private _directiveCache = new Map < Type < any > , cpl . CompileDirectiveMetadata > ( ) ;
private _pipeCache = new Map < Type < any > , cpl . CompilePipeMetadata > ( ) ;
private _ngModuleCache = new Map < Type < any > , cpl . CompileNgModuleMetadata > ( ) ;
private _ngModuleOfTypes = new Map < Type < any > , Type < any > > ( ) ;
2016-03-29 20:15:07 -04:00
private _anonymousTypes = new Map < Object , number > ( ) ;
private _anonymousTypeIndex = 0 ;
2015-09-14 18:59:09 -04:00
2016-06-08 19:38:52 -04:00
constructor (
2016-07-18 06:50:31 -04:00
private _ngModuleResolver : NgModuleResolver , private _directiveResolver : DirectiveResolver ,
2016-07-28 09:31:26 -04:00
private _pipeResolver : PipeResolver , private _config : CompilerConfig ,
2016-07-29 05:10:30 -04:00
private _console : Console , private _schemaRegistry : ElementSchemaRegistry ,
private _reflector : ReflectorReader = reflector ) { }
2015-09-14 18:59:09 -04:00
2016-04-20 21:10:19 -04:00
private sanitizeTokenName ( token : any ) : string {
let identifier = stringify ( token ) ;
if ( identifier . indexOf ( '(' ) >= 0 ) {
// case: anonymous functions!
let found = this . _anonymousTypes . get ( token ) ;
if ( isBlank ( found ) ) {
this . _anonymousTypes . set ( token , this . _anonymousTypeIndex ++ ) ;
found = this . _anonymousTypes . get ( token ) ;
}
identifier = ` anonymous_token_ ${ found } _ ` ;
2016-03-29 20:15:07 -04:00
}
2016-04-20 21:10:19 -04:00
return sanitizeIdentifier ( identifier ) ;
2016-03-29 20:15:07 -04:00
}
2016-08-10 21:21:28 -04:00
clearCacheFor ( type : Type < any > ) {
2016-06-28 12:54:42 -04:00
this . _directiveCache . delete ( type ) ;
this . _pipeCache . delete ( type ) ;
2016-07-18 06:50:31 -04:00
this . _ngModuleOfTypes . delete ( type ) ;
// Clear all of the NgModuleMetadata as they contain transitive information!
this . _ngModuleCache . clear ( ) ;
2016-06-24 11:46:43 -04:00
}
clearCache() {
this . _directiveCache . clear ( ) ;
this . _pipeCache . clear ( ) ;
2016-07-18 06:50:31 -04:00
this . _ngModuleCache . clear ( ) ;
this . _ngModuleOfTypes . clear ( ) ;
2016-06-24 11:46:43 -04:00
}
2016-05-26 18:07:51 -04:00
getAnimationEntryMetadata ( entry : AnimationEntryMetadata ) : cpl . CompileAnimationEntryMetadata {
2016-05-25 15:46:22 -04:00
var defs = entry . definitions . map ( def = > this . getAnimationStateMetadata ( def ) ) ;
return new cpl . CompileAnimationEntryMetadata ( entry . name , defs ) ;
}
2016-05-26 18:07:51 -04:00
getAnimationStateMetadata ( value : AnimationStateMetadata ) : cpl . CompileAnimationStateMetadata {
if ( value instanceof AnimationStateDeclarationMetadata ) {
2016-05-25 15:46:22 -04:00
var styles = this . getAnimationStyleMetadata ( value . styles ) ;
return new cpl . CompileAnimationStateDeclarationMetadata ( value . stateNameExpr , styles ) ;
2016-05-26 18:07:51 -04:00
} else if ( value instanceof AnimationStateTransitionMetadata ) {
2016-06-08 19:38:52 -04:00
return new cpl . CompileAnimationStateTransitionMetadata (
value . stateChangeExpr , this . getAnimationMetadata ( value . steps ) ) ;
2016-05-25 15:46:22 -04:00
}
return null ;
}
2016-05-26 18:07:51 -04:00
getAnimationStyleMetadata ( value : AnimationStyleMetadata ) : cpl . CompileAnimationStyleMetadata {
2016-05-25 15:46:22 -04:00
return new cpl . CompileAnimationStyleMetadata ( value . offset , value . styles ) ;
}
2016-05-26 18:07:51 -04:00
getAnimationMetadata ( value : AnimationMetadata ) : cpl . CompileAnimationMetadata {
if ( value instanceof AnimationStyleMetadata ) {
2016-05-25 15:46:22 -04:00
return this . getAnimationStyleMetadata ( value ) ;
2016-05-26 18:07:51 -04:00
} else if ( value instanceof AnimationKeyframesSequenceMetadata ) {
2016-06-08 19:38:52 -04:00
return new cpl . CompileAnimationKeyframesSequenceMetadata (
value . steps . map ( entry = > this . getAnimationStyleMetadata ( entry ) ) ) ;
2016-05-26 18:07:51 -04:00
} else if ( value instanceof AnimationAnimateMetadata ) {
2016-06-08 19:38:52 -04:00
let animateData =
< cpl.CompileAnimationStyleMetadata | cpl.CompileAnimationKeyframesSequenceMetadata > this
. getAnimationMetadata ( value . styles ) ;
2016-05-25 15:46:22 -04:00
return new cpl . CompileAnimationAnimateMetadata ( value . timings , animateData ) ;
2016-05-26 18:07:51 -04:00
} else if ( value instanceof AnimationWithStepsMetadata ) {
2016-05-25 15:46:22 -04:00
var steps = value . steps . map ( step = > this . getAnimationMetadata ( step ) ) ;
2016-05-26 18:07:51 -04:00
if ( value instanceof AnimationGroupMetadata ) {
2016-05-25 15:46:22 -04:00
return new cpl . CompileAnimationGroupMetadata ( steps ) ;
} else {
return new cpl . CompileAnimationSequenceMetadata ( steps ) ;
}
}
return null ;
}
2016-08-10 21:21:28 -04:00
getDirectiveMetadata ( directiveType : Type < any > , throwIfNotFound = true ) :
cpl . CompileDirectiveMetadata {
2016-06-28 12:54:42 -04:00
directiveType = resolveForwardRef ( directiveType ) ;
2015-12-02 13:35:51 -05:00
var meta = this . _directiveCache . get ( directiveType ) ;
2015-09-14 18:59:09 -04:00
if ( isBlank ( meta ) ) {
2016-07-18 06:50:31 -04:00
var dirMeta = this . _directiveResolver . resolve ( directiveType , throwIfNotFound ) ;
if ( ! dirMeta ) {
return null ;
}
2016-06-12 00:23:37 -04:00
var templateMeta : cpl.CompileTemplateMetadata = null ;
2016-06-22 20:25:42 -04:00
var changeDetectionStrategy : ChangeDetectionStrategy = null ;
var viewProviders : Array < cpl.CompileProviderMetadata | cpl.CompileTypeMetadata | any [ ] > = [ ] ;
2016-05-02 19:45:43 -04:00
var module Url = staticTypeModuleUrl ( directiveType ) ;
2016-07-28 09:31:26 -04:00
var viewDirectiveTypes : cpl.CompileTypeMetadata [ ] = [ ] ;
var viewPipeTypes : cpl.CompileTypeMetadata [ ] = [ ] ;
2016-07-25 03:36:30 -04:00
var entryComponentTypes : cpl.CompileTypeMetadata [ ] = [ ] ;
2016-07-28 13:39:10 -04:00
let selector = dirMeta . selector ;
2016-04-28 20:50:03 -04:00
if ( dirMeta instanceof ComponentMetadata ) {
var cmpMeta = < ComponentMetadata > dirMeta ;
2016-07-28 09:31:26 -04:00
assertArrayOfStrings ( 'styles' , cmpMeta . styles ) ;
assertInterpolationSymbols ( 'interpolation' , cmpMeta . interpolation ) ;
var animations = isPresent ( cmpMeta . animations ) ?
cmpMeta . animations . map ( e = > this . getAnimationEntryMetadata ( e ) ) :
2016-06-08 19:38:52 -04:00
null ;
2016-07-28 09:31:26 -04:00
assertArrayOfStrings ( 'styles' , cmpMeta . styles ) ;
assertArrayOfStrings ( 'styleUrls' , cmpMeta . styleUrls ) ;
2016-05-25 15:46:22 -04:00
2015-09-18 13:33:23 -04:00
templateMeta = new cpl . CompileTemplateMetadata ( {
2016-07-28 09:31:26 -04:00
encapsulation : cmpMeta.encapsulation ,
template : cmpMeta.template ,
templateUrl : cmpMeta.templateUrl ,
styles : cmpMeta.styles ,
styleUrls : cmpMeta.styleUrls ,
2016-06-20 12:52:41 -04:00
animations : animations ,
2016-07-28 09:31:26 -04:00
interpolation : cmpMeta.interpolation
2015-09-14 18:59:09 -04:00
} ) ;
2015-10-23 18:55:48 -04:00
changeDetectionStrategy = cmpMeta . changeDetection ;
2016-01-06 17:13:44 -05:00
if ( isPresent ( dirMeta . viewProviders ) ) {
2016-06-21 20:27:27 -04:00
viewProviders = this . getProvidersMetadata (
2016-07-07 13:05:55 -04:00
verifyNonBlankProviders ( directiveType , dirMeta . viewProviders , 'viewProviders' ) , [ ] ) ;
2016-01-06 17:13:44 -05:00
}
2016-05-02 19:45:43 -04:00
module Url = componentModuleUrl ( this . _reflector , directiveType , cmpMeta ) ;
2016-07-25 03:36:30 -04:00
if ( cmpMeta . entryComponents ) {
entryComponentTypes =
flattenArray ( cmpMeta . entryComponents )
2016-07-28 09:31:26 -04:00
. map ( ( type ) = > this . getTypeMetadata ( type , staticTypeModuleUrl ( type ) ) ) ;
}
if ( cmpMeta . directives ) {
viewDirectiveTypes = flattenArray ( cmpMeta . directives ) . map ( ( type ) = > {
if ( ! type ) {
throw new BaseException (
` Unexpected directive value ' ${ type } ' on the View of component ' ${ stringify ( directiveType ) } ' ` ) ;
}
return this . getTypeMetadata ( type , staticTypeModuleUrl ( type ) ) ;
} ) ;
}
if ( cmpMeta . pipes ) {
viewPipeTypes = flattenArray ( cmpMeta . pipes ) . map ( ( type ) = > {
if ( ! type ) {
throw new BaseException (
` Unexpected pipe value ' ${ type } ' on the View of component ' ${ stringify ( directiveType ) } ' ` ) ;
}
return this . getTypeMetadata ( type , staticTypeModuleUrl ( type ) ) ;
} ) ;
2016-06-22 17:06:23 -04:00
}
2016-07-28 13:39:10 -04:00
if ( ! selector ) {
selector = this . _schemaRegistry . getDefaultComponentElementName ( ) ;
}
} else {
if ( ! selector ) {
throw new BaseException (
` Directive ${ stringify ( directiveType ) } has no selector, please add it! ` ) ;
}
2016-01-06 17:13:44 -05:00
}
2016-06-22 20:25:42 -04:00
var providers : Array < cpl.CompileProviderMetadata | cpl.CompileTypeMetadata | any [ ] > = [ ] ;
2016-01-06 17:13:44 -05:00
if ( isPresent ( dirMeta . providers ) ) {
2016-06-21 20:27:27 -04:00
providers = this . getProvidersMetadata (
2016-07-07 13:05:55 -04:00
verifyNonBlankProviders ( directiveType , dirMeta . providers , 'providers' ) ,
2016-07-25 03:36:30 -04:00
entryComponentTypes ) ;
2016-01-06 17:13:44 -05:00
}
2016-07-07 13:05:55 -04:00
var queries : cpl.CompileQueryMetadata [ ] = [ ] ;
var viewQueries : cpl.CompileQueryMetadata [ ] = [ ] ;
2016-01-06 17:13:44 -05:00
if ( isPresent ( dirMeta . queries ) ) {
2016-06-04 22:46:03 -04:00
queries = this . getQueriesMetadata ( dirMeta . queries , false , directiveType ) ;
viewQueries = this . getQueriesMetadata ( dirMeta . queries , true , directiveType ) ;
2015-09-14 18:59:09 -04:00
}
2015-09-18 13:33:23 -04:00
meta = cpl . CompileDirectiveMetadata . create ( {
2016-07-28 13:39:10 -04:00
selector : selector ,
2015-10-23 18:55:48 -04:00
exportAs : dirMeta.exportAs ,
2015-09-14 18:59:09 -04:00
isComponent : isPresent ( templateMeta ) ,
2016-05-02 19:45:43 -04:00
type : this . getTypeMetadata ( directiveType , module Url ) ,
2015-09-14 18:59:09 -04:00
template : templateMeta ,
2015-09-18 13:33:23 -04:00
changeDetection : changeDetectionStrategy ,
2015-10-23 18:55:48 -04:00
inputs : dirMeta.inputs ,
outputs : dirMeta.outputs ,
host : dirMeta.host ,
2016-01-06 17:13:44 -05:00
providers : providers ,
viewProviders : viewProviders ,
queries : queries ,
2016-06-22 17:06:23 -04:00
viewQueries : viewQueries ,
2016-07-28 09:31:26 -04:00
viewDirectives : viewDirectiveTypes ,
viewPipes : viewPipeTypes ,
2016-07-25 03:36:30 -04:00
entryComponents : entryComponentTypes
2015-09-14 18:59:09 -04:00
} ) ;
2015-12-02 13:35:51 -05:00
this . _directiveCache . set ( directiveType , meta ) ;
}
return meta ;
}
2016-07-18 06:50:31 -04:00
getNgModuleMetadata ( module Type : any , throwIfNotFound = true ) : cpl . CompileNgModuleMetadata {
2016-06-28 12:54:42 -04:00
module Type = resolveForwardRef ( module Type ) ;
2016-07-18 06:50:31 -04:00
var compileMeta = this . _ngModuleCache . get ( module Type ) ;
if ( ! compileMeta ) {
const meta = this . _ngModuleResolver . resolve ( module Type , throwIfNotFound ) ;
2016-06-28 12:54:42 -04:00
if ( ! meta ) {
2016-07-18 06:50:31 -04:00
return null ;
2016-06-28 12:54:42 -04:00
}
2016-07-18 06:50:31 -04:00
const declaredDirectives : cpl.CompileDirectiveMetadata [ ] = [ ] ;
const exportedDirectives : cpl.CompileDirectiveMetadata [ ] = [ ] ;
const declaredPipes : cpl.CompilePipeMetadata [ ] = [ ] ;
const exportedPipes : cpl.CompilePipeMetadata [ ] = [ ] ;
const importedModules : cpl.CompileNgModuleMetadata [ ] = [ ] ;
const exportedModules : cpl.CompileNgModuleMetadata [ ] = [ ] ;
2016-07-25 04:39:50 -04:00
const providers : any [ ] = [ ] ;
const entryComponents : cpl.CompileTypeMetadata [ ] = [ ] ;
2016-08-02 09:54:08 -04:00
const bootstrapComponents : cpl.CompileTypeMetadata [ ] = [ ] ;
2016-07-25 06:02:57 -04:00
const schemas : SchemaMetadata [ ] = [ ] ;
2016-07-18 06:50:31 -04:00
if ( meta . imports ) {
flattenArray ( meta . imports ) . forEach ( ( importedType ) = > {
2016-08-10 21:21:28 -04:00
let importedModuleType : Type < any > ;
2016-07-25 04:39:50 -04:00
if ( isValidType ( importedType ) ) {
importedModuleType = importedType ;
} else if ( importedType && importedType . ngModule ) {
const module WithProviders : ModuleWithProviders = importedType ;
importedModuleType = module WithProviders.ngModule ;
if ( module WithProviders.providers ) {
providers . push (
. . . this . getProvidersMetadata ( module WithProviders.providers , entryComponents ) ) ;
}
2016-07-18 06:50:31 -04:00
}
2016-07-25 04:39:50 -04:00
if ( importedModuleType ) {
2016-08-17 18:57:02 -04:00
let importedMeta = this . getNgModuleMetadata ( importedModuleType , false ) ;
if ( importedMeta === null ) {
throw new BaseException (
` Unexpected ${ this . _getTypeDescriptor ( importedType ) } ' ${ stringify ( importedType ) } ' imported by the module ' ${ stringify ( module Type ) } ' ` ) ;
}
importedModules . push ( importedMeta ) ;
2016-07-18 06:50:31 -04:00
} else {
throw new BaseException (
` Unexpected value ' ${ stringify ( importedType ) } ' imported by the module ' ${ stringify ( module Type ) } ' ` ) ;
}
} ) ;
}
if ( meta . exports ) {
flattenArray ( meta . exports ) . forEach ( ( exportedType ) = > {
if ( ! isValidType ( exportedType ) ) {
throw new BaseException (
` Unexpected value ' ${ stringify ( exportedType ) } ' exported by the module ' ${ stringify ( module Type ) } ' ` ) ;
}
let exportedDirMeta : cpl.CompileDirectiveMetadata ;
let exportedPipeMeta : cpl.CompilePipeMetadata ;
let exportedModuleMeta : cpl.CompileNgModuleMetadata ;
if ( exportedDirMeta = this . getDirectiveMetadata ( exportedType , false ) ) {
exportedDirectives . push ( exportedDirMeta ) ;
} else if ( exportedPipeMeta = this . getPipeMetadata ( exportedType , false ) ) {
exportedPipes . push ( exportedPipeMeta ) ;
} else if ( exportedModuleMeta = this . getNgModuleMetadata ( exportedType , false ) ) {
exportedModules . push ( exportedModuleMeta ) ;
} else {
throw new BaseException (
2016-08-17 18:57:02 -04:00
` Unexpected ${ this . _getTypeDescriptor ( exportedType ) } ' ${ stringify ( exportedType ) } ' exported by the module ' ${ stringify ( module Type ) } ' ` ) ;
2016-07-18 06:50:31 -04:00
}
} ) ;
2016-06-28 12:54:42 -04:00
}
2016-07-18 06:50:31 -04:00
// Note: This will be modified later, so we rely on
// getting a new instance every time!
const transitiveModule =
this . _getTransitiveNgModuleMetadata ( importedModules , exportedModules ) ;
if ( meta . declarations ) {
flattenArray ( meta . declarations ) . forEach ( ( declaredType ) = > {
if ( ! isValidType ( declaredType ) ) {
throw new BaseException (
` Unexpected value ' ${ stringify ( declaredType ) } ' declared by the module ' ${ stringify ( module Type ) } ' ` ) ;
}
let declaredDirMeta : cpl.CompileDirectiveMetadata ;
let declaredPipeMeta : cpl.CompilePipeMetadata ;
if ( declaredDirMeta = this . getDirectiveMetadata ( declaredType , false ) ) {
this . _addDirectiveToModule (
declaredDirMeta , module Type , transitiveModule , declaredDirectives , true ) ;
} else if ( declaredPipeMeta = this . getPipeMetadata ( declaredType , false ) ) {
this . _addPipeToModule (
declaredPipeMeta , module Type , transitiveModule , declaredPipes , true ) ;
} else {
throw new BaseException (
2016-08-17 18:57:02 -04:00
` Unexpected ${ this . _getTypeDescriptor ( declaredType ) } ' ${ stringify ( declaredType ) } ' declared by the module ' ${ stringify ( module Type ) } ' ` ) ;
2016-07-18 06:50:31 -04:00
}
feat(browser): use AppModules for bootstrap in the browser
This introduces the `BrowserModule` to be used for long form
bootstrap and offline compile bootstrap:
```
@AppModule({
modules: [BrowserModule],
precompile: [MainComponent],
providers: […], // additional providers
directives: […], // additional platform directives
pipes: […] // additional platform pipes
})
class MyModule {
constructor(appRef: ApplicationRef) {
appRef.bootstrap(MainComponent);
}
}
// offline compile
import {bootstrapModuleFactory} from ‘@angular/platform-browser’;
bootstrapModuleFactory(MyModuleNgFactory);
// runtime compile long form
import {bootstrapModule} from ‘@angular/platform-browser-dynamic’;
bootstrapModule(MyModule);
```
The short form, `bootstrap(...)`, can now creates a module on the fly,
given `directives`, `pipes, `providers`, `precompile` and `modules`
properties.
Related changes:
- make `SanitizationService`, `SecurityContext` public in `@angular/core` so that the offline compiler can resolve the token
- move `AnimationDriver` to `platform-browser` and make it
public so that the offline compiler can resolve the token
BREAKING CHANGES:
- short form bootstrap does no longer allow
to inject compiler internals (i.e. everything
from `@angular/compiler). Inject `Compiler` instead.
To provide custom providers for the compiler,
create a custom compiler via `browserCompiler({providers: [...]})`
and pass that into the `bootstrap` method.
2016-06-30 16:07:17 -04:00
} ) ;
}
2016-07-27 04:52:31 -04:00
// The providers of the module have to go last
// so that they overwrite any other provider we already added.
if ( meta . providers ) {
providers . push ( . . . this . getProvidersMetadata ( meta . providers , entryComponents ) ) ;
}
if ( meta . entryComponents ) {
entryComponents . push (
. . . flattenArray ( meta . entryComponents )
. map ( type = > this . getTypeMetadata ( type , staticTypeModuleUrl ( type ) ) ) ) ;
}
2016-08-02 09:54:08 -04:00
if ( meta . bootstrap ) {
bootstrapComponents . push (
. . . flattenArray ( meta . bootstrap )
. map ( type = > this . getTypeMetadata ( type , staticTypeModuleUrl ( type ) ) ) ) ;
}
entryComponents . push ( . . . bootstrapComponents ) ;
2016-07-27 04:52:31 -04:00
if ( meta . schemas ) {
schemas . push ( . . . flattenArray ( meta . schemas ) ) ;
}
2016-07-25 03:36:30 -04:00
transitiveModule . entryComponents . push ( . . . entryComponents ) ;
2016-07-18 06:50:31 -04:00
transitiveModule . providers . push ( . . . providers ) ;
compileMeta = new cpl . CompileNgModuleMetadata ( {
2016-06-28 12:54:42 -04:00
type : this . getTypeMetadata ( module Type , staticTypeModuleUrl ( module Type ) ) ,
providers : providers ,
2016-07-25 03:36:30 -04:00
entryComponents : entryComponents ,
2016-08-02 09:54:08 -04:00
bootstrapComponents : bootstrapComponents ,
2016-07-25 06:02:57 -04:00
schemas : schemas ,
2016-07-18 06:50:31 -04:00
declaredDirectives : declaredDirectives ,
exportedDirectives : exportedDirectives ,
declaredPipes : declaredPipes ,
exportedPipes : exportedPipes ,
importedModules : importedModules ,
exportedModules : exportedModules ,
transitiveModule : transitiveModule
2016-06-28 12:54:42 -04:00
} ) ;
2016-07-18 06:50:31 -04:00
transitiveModule . module s.push ( compileMeta ) ;
this . _verifyModule ( compileMeta ) ;
this . _ngModuleCache . set ( module Type , compileMeta ) ;
2016-06-28 12:54:42 -04:00
}
return compileMeta ;
}
2016-08-10 21:21:28 -04:00
addComponentToModule ( module Type : Type < any > , compType : Type < any > ) {
2016-07-18 06:50:31 -04:00
const module Meta = this . getNgModuleMetadata ( module Type ) ;
2016-07-25 03:36:30 -04:00
// Collect @Component.directives/pipes/entryComponents into our declared directives/pipes.
2016-07-18 06:50:31 -04:00
const compMeta = this . getDirectiveMetadata ( compType , false ) ;
this . _addDirectiveToModule (
compMeta , module Meta.type.runtime , module Meta.transitiveModule ,
module Meta.declaredDirectives ) ;
2016-07-25 03:36:30 -04:00
module Meta.transitiveModule.entryComponents.push ( compMeta . type ) ;
module Meta.entryComponents.push ( compMeta . type ) ;
2016-07-18 06:50:31 -04:00
this . _verifyModule ( module Meta ) ;
}
private _verifyModule ( module Meta : cpl . CompileNgModuleMetadata ) {
module Meta.exportedDirectives.forEach ( ( dirMeta ) = > {
if ( ! module Meta.transitiveModule.directivesSet.has ( dirMeta . type . runtime ) ) {
throw new BaseException (
` Can't export directive ${ stringify ( dirMeta . type . runtime ) } from ${ stringify ( module Meta.type.runtime ) } as it was neither declared nor imported! ` ) ;
}
} ) ;
module Meta.exportedPipes.forEach ( ( pipeMeta ) = > {
if ( ! module Meta.transitiveModule.pipesSet.has ( pipeMeta . type . runtime ) ) {
throw new BaseException (
` Can't export pipe ${ stringify ( pipeMeta . type . runtime ) } from ${ stringify ( module Meta.type.runtime ) } as it was neither declared nor imported! ` ) ;
}
} ) ;
2016-07-25 03:36:30 -04:00
module Meta.entryComponents.forEach ( ( entryComponentType ) = > {
if ( ! module Meta.transitiveModule.directivesSet.has ( entryComponentType . runtime ) ) {
2016-07-27 04:45:20 -04:00
this . _addDirectiveToModule (
this . getDirectiveMetadata ( entryComponentType . runtime ) , module Meta.type.runtime ,
module Meta.transitiveModule , module Meta.declaredDirectives ) ;
this . _console . warn (
` NgModule ${ stringify ( module Meta.type.runtime ) } uses ${ stringify ( entryComponentType . runtime ) } via "entryComponents" but it was neither declared nor imported! This warning will become an error after final. ` ) ;
2016-02-18 13:53:21 -05:00
}
2016-07-18 06:50:31 -04:00
} ) ;
2016-07-28 05:50:50 -04:00
// Collect @Component.directives/pipes/entryComponents into our declared
// directives/pipes. Do this last so that directives added by previous steps
// are considered as well!
module Meta.declaredDirectives.forEach (
( dirMeta ) = > { this . _getTransitiveViewDirectivesAndPipes ( dirMeta , module Meta ) ; } ) ;
2016-07-18 06:50:31 -04:00
}
2016-08-17 18:57:02 -04:00
private _getTypeDescriptor ( type : Type < any > ) : string {
if ( this . _directiveResolver . resolve ( type , false ) !== null ) {
return 'directive' ;
} else if ( this . _pipeResolver . resolve ( type , false ) !== null ) {
return 'pipe' ;
} else if ( this . _ngModuleResolver . resolve ( type , false ) !== null ) {
return 'module' ;
} else if ( ( type as any ) . provide ) {
return 'provider' ;
} else {
return 'value' ;
}
}
2016-08-10 21:21:28 -04:00
private _addTypeToModule ( type : Type < any > , module Type : Type < any > ) {
2016-07-18 06:50:31 -04:00
const oldModule = this . _ngModuleOfTypes . get ( type ) ;
if ( oldModule && oldModule !== module Type ) {
throw new BaseException (
` Type ${ stringify ( type ) } is part of the declarations of 2 modules: ${ stringify ( oldModule ) } and ${ stringify ( module Type ) } ! ` ) ;
2016-02-18 13:53:21 -05:00
}
2016-07-18 06:50:31 -04:00
this . _ngModuleOfTypes . set ( type , module Type ) ;
}
private _getTransitiveViewDirectivesAndPipes (
2016-07-28 05:50:50 -04:00
compMeta : cpl.CompileDirectiveMetadata , module Meta : cpl . CompileNgModuleMetadata ) {
2016-07-18 06:50:31 -04:00
if ( ! compMeta . isComponent ) {
return ;
}
2016-08-10 21:21:28 -04:00
const addPipe = ( pipeType : Type < any > ) = > {
2016-07-18 06:50:31 -04:00
const pipeMeta = this . getPipeMetadata ( pipeType ) ;
2016-07-28 05:50:50 -04:00
this . _addPipeToModule (
pipeMeta , module Meta.type.runtime , module Meta.transitiveModule , module Meta.declaredPipes ) ;
2016-07-18 06:50:31 -04:00
} ;
2016-08-10 21:21:28 -04:00
const addDirective = ( dirType : Type < any > ) = > {
2016-07-18 06:50:31 -04:00
const dirMeta = this . getDirectiveMetadata ( dirType ) ;
2016-07-28 05:50:50 -04:00
if ( this . _addDirectiveToModule (
dirMeta , module Meta.type.runtime , module Meta.transitiveModule ,
module Meta.declaredDirectives ) ) {
this . _getTransitiveViewDirectivesAndPipes ( dirMeta , module Meta ) ;
2016-07-18 06:50:31 -04:00
}
} ;
2016-07-28 09:31:26 -04:00
if ( compMeta . viewPipes ) {
compMeta . viewPipes . forEach ( ( cplType ) = > addPipe ( cplType . runtime ) ) ;
2016-07-18 06:50:31 -04:00
}
2016-07-28 09:31:26 -04:00
if ( compMeta . viewDirectives ) {
compMeta . viewDirectives . forEach ( ( cplType ) = > addDirective ( cplType . runtime ) ) ;
2016-07-18 06:50:31 -04:00
}
2016-07-28 05:50:50 -04:00
compMeta . entryComponents . forEach ( ( entryComponentType ) = > {
if ( ! module Meta.transitiveModule.directivesSet.has ( entryComponentType . runtime ) ) {
this . _console . warn (
` Component ${ stringify ( compMeta . type . runtime ) } in NgModule ${ stringify ( module Meta.type.runtime ) } uses ${ stringify ( entryComponentType . runtime ) } via "entryComponents" but it was neither declared nor imported into the module! This warning will become an error after final. ` ) ;
addDirective ( entryComponentType . runtime ) ;
}
} ) ;
2016-07-18 06:50:31 -04:00
}
private _getTransitiveNgModuleMetadata (
importedModules : cpl.CompileNgModuleMetadata [ ] ,
exportedModules : cpl.CompileNgModuleMetadata [ ] ) : cpl . TransitiveCompileNgModuleMetadata {
2016-07-25 03:36:30 -04:00
// collect `providers` / `entryComponents` from all imported and all exported modules
2016-07-18 06:50:31 -04:00
const transitiveModules = getTransitiveModules ( importedModules . concat ( exportedModules ) , true ) ;
const providers = flattenArray ( transitiveModules . map ( ( ngModule ) = > ngModule . providers ) ) ;
2016-07-25 03:36:30 -04:00
const entryComponents =
flattenArray ( transitiveModules . map ( ( ngModule ) = > ngModule . entryComponents ) ) ;
2016-07-18 06:50:31 -04:00
const transitiveExportedModules = getTransitiveModules ( importedModules , false ) ;
const directives =
flattenArray ( transitiveExportedModules . map ( ( ngModule ) = > ngModule . exportedDirectives ) ) ;
const pipes = flattenArray ( transitiveExportedModules . map ( ( ngModule ) = > ngModule . exportedPipes ) ) ;
return new cpl . TransitiveCompileNgModuleMetadata (
2016-07-25 03:36:30 -04:00
transitiveModules , providers , entryComponents , directives , pipes ) ;
2016-07-18 06:50:31 -04:00
}
private _addDirectiveToModule (
dirMeta : cpl.CompileDirectiveMetadata , module Type : any ,
transitiveModule : cpl.TransitiveCompileNgModuleMetadata ,
declaredDirectives : cpl.CompileDirectiveMetadata [ ] , force : boolean = false ) : boolean {
if ( force || ! transitiveModule . directivesSet . has ( dirMeta . type . runtime ) ) {
transitiveModule . directivesSet . add ( dirMeta . type . runtime ) ;
transitiveModule . directives . push ( dirMeta ) ;
declaredDirectives . push ( dirMeta ) ;
this . _addTypeToModule ( dirMeta . type . runtime , module Type ) ;
return true ;
}
return false ;
}
private _addPipeToModule (
pipeMeta : cpl.CompilePipeMetadata , module Type : any ,
transitiveModule : cpl.TransitiveCompileNgModuleMetadata ,
declaredPipes : cpl.CompilePipeMetadata [ ] , force : boolean = false ) : boolean {
if ( force || ! transitiveModule . pipesSet . has ( pipeMeta . type . runtime ) ) {
transitiveModule . pipesSet . add ( pipeMeta . type . runtime ) ;
transitiveModule . pipes . push ( pipeMeta ) ;
declaredPipes . push ( pipeMeta ) ;
this . _addTypeToModule ( pipeMeta . type . runtime , module Type ) ;
return true ;
}
return false ;
2016-02-18 13:53:21 -05:00
}
2016-08-10 21:21:28 -04:00
getTypeMetadata ( type : Type < any > , module Url : string , dependencies : any [ ] = null ) :
2016-06-18 12:42:34 -04:00
cpl . CompileTypeMetadata {
2016-06-28 12:54:42 -04:00
type = resolveForwardRef ( type ) ;
2016-01-06 17:13:44 -05:00
return new cpl . CompileTypeMetadata ( {
2016-04-20 21:10:19 -04:00
name : this.sanitizeTokenName ( type ) ,
2016-01-06 17:13:44 -05:00
module Url : module Url ,
runtime : type ,
2016-08-02 04:12:24 -04:00
diDeps : this.getDependenciesMetadata ( type , dependencies ) ,
lifecycleHooks : LIFECYCLE_HOOKS_VALUES.filter ( hook = > hasLifecycleHook ( hook , type ) ) ,
2016-01-06 17:13:44 -05:00
} ) ;
}
2016-06-18 12:42:34 -04:00
getFactoryMetadata ( factory : Function , module Url : string , dependencies : any [ ] = null ) :
cpl . CompileFactoryMetadata {
2016-06-28 12:54:42 -04:00
factory = resolveForwardRef ( factory ) ;
2016-01-06 17:13:44 -05:00
return new cpl . CompileFactoryMetadata ( {
2016-04-20 21:10:19 -04:00
name : this.sanitizeTokenName ( factory ) ,
2016-01-06 17:13:44 -05:00
module Url : module Url ,
runtime : factory ,
2016-06-18 12:42:34 -04:00
diDeps : this.getDependenciesMetadata ( factory , dependencies )
2016-01-06 17:13:44 -05:00
} ) ;
}
2016-08-10 21:21:28 -04:00
getPipeMetadata ( pipeType : Type < any > , throwIfNotFound = true ) : cpl . CompilePipeMetadata {
2016-06-28 12:54:42 -04:00
pipeType = resolveForwardRef ( pipeType ) ;
2015-12-02 13:35:51 -05:00
var meta = this . _pipeCache . get ( pipeType ) ;
if ( isBlank ( meta ) ) {
2016-07-18 06:50:31 -04:00
var pipeMeta = this . _pipeResolver . resolve ( pipeType , throwIfNotFound ) ;
if ( ! pipeMeta ) {
return null ;
}
2015-12-02 13:35:51 -05:00
meta = new cpl . CompilePipeMetadata ( {
2016-02-18 13:53:21 -05:00
type : this . getTypeMetadata ( pipeType , staticTypeModuleUrl ( pipeType ) ) ,
2015-12-02 13:35:51 -05:00
name : pipeMeta.name ,
2016-08-02 04:12:24 -04:00
pure : pipeMeta.pure
2015-12-02 13:35:51 -05:00
} ) ;
this . _pipeCache . set ( pipeType , meta ) ;
2015-09-14 18:59:09 -04:00
}
return meta ;
}
2016-08-10 21:21:28 -04:00
getDependenciesMetadata ( typeOrFunc : Type < any > | Function , dependencies : any [ ] ) :
2016-06-08 19:38:52 -04:00
cpl . CompileDiDependencyMetadata [ ] {
2016-06-09 19:07:06 -04:00
let hasUnknownDeps = false ;
2016-02-18 13:53:21 -05:00
let params = isPresent ( dependencies ) ? dependencies : this._reflector.parameters ( typeOrFunc ) ;
if ( isBlank ( params ) ) {
params = [ ] ;
2016-01-06 17:13:44 -05:00
}
2016-06-09 19:07:06 -04:00
let dependenciesMetadata : cpl.CompileDiDependencyMetadata [ ] = params . map ( ( param ) = > {
2016-02-18 13:53:21 -05:00
let isAttribute = false ;
let isHost = false ;
let isSelf = false ;
let isSkipSelf = false ;
let isOptional = false ;
2016-04-28 20:50:03 -04:00
let query : QueryMetadata = null ;
let viewQuery : ViewQueryMetadata = null ;
2016-06-17 13:57:50 -04:00
var token : any = null ;
2016-02-18 13:53:21 -05:00
if ( isArray ( param ) ) {
2016-06-08 19:38:52 -04:00
( < any [ ] > param ) . forEach ( ( paramEntry ) = > {
if ( paramEntry instanceof HostMetadata ) {
isHost = true ;
} else if ( paramEntry instanceof SelfMetadata ) {
isSelf = true ;
} else if ( paramEntry instanceof SkipSelfMetadata ) {
isSkipSelf = true ;
} else if ( paramEntry instanceof OptionalMetadata ) {
isOptional = true ;
} else if ( paramEntry instanceof AttributeMetadata ) {
isAttribute = true ;
token = paramEntry . attributeName ;
} else if ( paramEntry instanceof QueryMetadata ) {
if ( paramEntry . isViewQuery ) {
viewQuery = paramEntry ;
} else {
query = paramEntry ;
}
} else if ( paramEntry instanceof InjectMetadata ) {
token = paramEntry . token ;
} else if ( isValidType ( paramEntry ) && isBlank ( token ) ) {
token = paramEntry ;
}
} ) ;
2016-01-06 17:13:44 -05:00
} else {
2016-02-18 13:53:21 -05:00
token = param ;
2016-01-06 17:13:44 -05:00
}
2016-02-18 13:53:21 -05:00
if ( isBlank ( token ) ) {
2016-06-09 19:07:06 -04:00
hasUnknownDeps = true ;
2016-02-18 13:53:21 -05:00
return null ;
2016-01-06 17:13:44 -05:00
}
return new cpl . CompileDiDependencyMetadata ( {
isAttribute : isAttribute ,
2016-02-18 13:53:21 -05:00
isHost : isHost ,
isSelf : isSelf ,
isSkipSelf : isSkipSelf ,
isOptional : isOptional ,
2016-06-04 22:46:03 -04:00
query : isPresent ( query ) ? this . getQueryMetadata ( query , null , typeOrFunc ) : null ,
viewQuery : isPresent ( viewQuery ) ? this . getQueryMetadata ( viewQuery , null , typeOrFunc ) : null ,
2016-02-18 13:53:21 -05:00
token : this.getTokenMetadata ( token )
2016-01-06 17:13:44 -05:00
} ) ;
2016-02-18 13:53:21 -05:00
2016-01-06 17:13:44 -05:00
} ) ;
2016-06-09 19:07:06 -04:00
if ( hasUnknownDeps ) {
2016-06-08 19:38:52 -04:00
let depsTokens =
dependenciesMetadata . map ( ( dep ) = > { return dep ? stringify ( dep . token ) : '?' ; } )
. join ( ', ' ) ;
throw new BaseException (
` Can't resolve all parameters for ${ stringify ( typeOrFunc ) } : ( ${ depsTokens } ). ` ) ;
2016-06-09 19:07:06 -04:00
}
return dependenciesMetadata ;
2016-01-06 17:13:44 -05:00
}
getTokenMetadata ( token : any ) : cpl . CompileTokenMetadata {
token = resolveForwardRef ( token ) ;
2016-06-08 18:45:15 -04:00
var compileToken : any /** TODO #9100 */ ;
2016-01-06 17:13:44 -05:00
if ( isString ( token ) ) {
compileToken = new cpl . CompileTokenMetadata ( { value : token } ) ;
} else {
2016-04-20 21:10:19 -04:00
compileToken = new cpl . CompileTokenMetadata ( {
2016-02-18 13:53:21 -05:00
identifier : new cpl . CompileIdentifierMetadata ( {
runtime : token ,
name : this.sanitizeTokenName ( token ) ,
module Url : staticTypeModuleUrl ( token )
} )
2016-04-20 21:10:19 -04:00
} ) ;
2016-01-06 17:13:44 -05:00
}
return compileToken ;
}
2016-08-15 22:37:42 -04:00
getProvidersMetadata ( providers : Provider [ ] , targetEntryComponents : cpl.CompileTypeMetadata [ ] ) :
2016-06-08 19:38:52 -04:00
Array < cpl.CompileProviderMetadata | cpl.CompileTypeMetadata | any [ ] > {
2016-07-07 13:05:55 -04:00
const compileProviders : Array < cpl.CompileProviderMetadata | cpl.CompileTypeMetadata | any [ ] > = [ ] ;
2016-08-15 22:37:42 -04:00
providers . forEach ( ( provider : any ) = > {
2016-01-06 17:13:44 -05:00
provider = resolveForwardRef ( provider ) ;
2016-08-15 22:37:42 -04:00
if ( provider && typeof provider == 'object' && provider . hasOwnProperty ( 'provide' ) ) {
provider = new cpl . ProviderMeta ( provider . provide , provider ) ;
2016-07-07 13:05:55 -04:00
}
let compileProvider : cpl.CompileProviderMetadata | cpl . CompileTypeMetadata | any [ ] ;
2016-01-06 17:13:44 -05:00
if ( isArray ( provider ) ) {
2016-07-25 03:36:30 -04:00
compileProvider = this . getProvidersMetadata ( provider , targetEntryComponents ) ;
2016-08-15 22:37:42 -04:00
} else if ( provider instanceof cpl . ProviderMeta ) {
2016-07-07 13:05:55 -04:00
let tokenMeta = this . getTokenMetadata ( provider . token ) ;
2016-07-25 03:36:30 -04:00
if ( tokenMeta . equalsTo ( identifierToken ( Identifiers . ANALYZE_FOR_ENTRY_COMPONENTS ) ) ) {
targetEntryComponents . push ( . . . this . _getEntryComponentsFromProvider ( provider ) ) ;
2016-07-07 13:05:55 -04:00
} else {
compileProvider = this . getProviderMetadata ( provider ) ;
}
2016-06-28 12:54:42 -04:00
} else if ( isValidType ( provider ) ) {
2016-07-07 13:05:55 -04:00
compileProvider = this . getTypeMetadata ( provider , staticTypeModuleUrl ( provider ) ) ;
2016-06-28 12:54:42 -04:00
} else {
throw new BaseException (
` Invalid provider - only instances of Provider and Type are allowed, got: ${ stringify ( provider ) } ` ) ;
2016-01-06 17:13:44 -05:00
}
2016-07-07 13:05:55 -04:00
if ( compileProvider ) {
compileProviders . push ( compileProvider ) ;
}
} ) ;
return compileProviders ;
}
2016-08-15 22:37:42 -04:00
private _getEntryComponentsFromProvider ( provider : cpl.ProviderMeta ) : cpl . CompileTypeMetadata [ ] {
2016-07-07 13:05:55 -04:00
let components : cpl.CompileTypeMetadata [ ] = [ ] ;
let collectedIdentifiers : cpl.CompileIdentifierMetadata [ ] = [ ] ;
if ( provider . useFactory || provider . useExisting || provider . useClass ) {
2016-07-25 03:36:30 -04:00
throw new BaseException ( ` The ANALYZE_FOR_ENTRY_COMPONENTS token only supports useValue! ` ) ;
2016-07-07 13:05:55 -04:00
}
if ( ! provider . multi ) {
2016-07-25 03:36:30 -04:00
throw new BaseException (
` The ANALYZE_FOR_ENTRY_COMPONENTS token only supports 'multi = true'! ` ) ;
2016-07-07 13:05:55 -04:00
}
convertToCompileValue ( provider . useValue , collectedIdentifiers ) ;
collectedIdentifiers . forEach ( ( identifier ) = > {
2016-07-18 06:50:31 -04:00
let dirMeta = this . getDirectiveMetadata ( identifier . runtime , false ) ;
2016-07-07 13:05:55 -04:00
if ( dirMeta ) {
components . push ( dirMeta . type ) ;
}
2016-01-06 17:13:44 -05:00
} ) ;
2016-07-07 13:05:55 -04:00
return components ;
2016-01-06 17:13:44 -05:00
}
2016-08-15 22:37:42 -04:00
getProviderMetadata ( provider : cpl.ProviderMeta ) : cpl . CompileProviderMetadata {
2016-06-18 12:42:34 -04:00
var compileDeps : cpl.CompileDiDependencyMetadata [ ] ;
var compileTypeMetadata : cpl.CompileTypeMetadata = null ;
var compileFactoryMetadata : cpl.CompileFactoryMetadata = null ;
2016-01-06 17:13:44 -05:00
if ( isPresent ( provider . useClass ) ) {
2016-06-18 12:42:34 -04:00
compileTypeMetadata = this . getTypeMetadata (
provider . useClass , staticTypeModuleUrl ( provider . useClass ) , provider . dependencies ) ;
compileDeps = compileTypeMetadata . diDeps ;
2016-01-06 17:13:44 -05:00
} else if ( isPresent ( provider . useFactory ) ) {
2016-06-18 12:42:34 -04:00
compileFactoryMetadata = this . getFactoryMetadata (
provider . useFactory , staticTypeModuleUrl ( provider . useFactory ) , provider . dependencies ) ;
compileDeps = compileFactoryMetadata . diDeps ;
2016-01-06 17:13:44 -05:00
}
2016-06-18 12:42:34 -04:00
2016-01-06 17:13:44 -05:00
return new cpl . CompileProviderMetadata ( {
token : this.getTokenMetadata ( provider . token ) ,
2016-06-18 12:42:34 -04:00
useClass : compileTypeMetadata ,
2016-07-07 13:05:55 -04:00
useValue : convertToCompileValue ( provider . useValue , [ ] ) ,
2016-06-18 12:42:34 -04:00
useFactory : compileFactoryMetadata ,
2016-01-06 17:13:44 -05:00
useExisting : isPresent ( provider . useExisting ) ? this . getTokenMetadata ( provider . useExisting ) :
null ,
deps : compileDeps ,
multi : provider.multi
} ) ;
}
2016-06-08 19:38:52 -04:00
getQueriesMetadata (
queries : { [ key : string ] : QueryMetadata } , isViewQuery : boolean ,
2016-08-10 21:21:28 -04:00
directiveType : Type < any > ) : cpl . CompileQueryMetadata [ ] {
2016-06-22 20:25:42 -04:00
var res : cpl.CompileQueryMetadata [ ] = [ ] ;
StringMapWrapper . forEach ( queries , ( query : QueryMetadata , propertyName : string ) = > {
if ( query . isViewQuery === isViewQuery ) {
res . push ( this . getQueryMetadata ( query , propertyName , directiveType ) ) ;
}
} ) ;
return res ;
2016-01-06 17:13:44 -05:00
}
2016-08-10 21:21:28 -04:00
getQueryMetadata ( q : QueryMetadata , propertyName : string , typeOrFunc : Type < any > | Function ) :
2016-06-08 19:38:52 -04:00
cpl . CompileQueryMetadata {
2016-06-17 13:57:50 -04:00
var selectors : cpl.CompileTokenMetadata [ ] ;
2016-01-06 17:13:44 -05:00
if ( q . isVarBindingQuery ) {
selectors = q . varBindings . map ( varName = > this . getTokenMetadata ( varName ) ) ;
} else {
2016-06-04 22:46:03 -04:00
if ( ! isPresent ( q . selector ) ) {
2016-06-08 19:38:52 -04:00
throw new BaseException (
` Can't construct a query for the property " ${ propertyName } " of " ${ stringify ( typeOrFunc ) } " since the query selector wasn't defined. ` ) ;
2016-06-04 22:46:03 -04:00
}
2016-01-06 17:13:44 -05:00
selectors = [ this . getTokenMetadata ( q . selector ) ] ;
}
return new cpl . CompileQueryMetadata ( {
selectors : selectors ,
first : q.first ,
descendants : q.descendants ,
2016-04-18 16:24:42 -04:00
propertyName : propertyName ,
read : isPresent ( q . read ) ? this . getTokenMetadata ( q . read ) : null
2016-01-06 17:13:44 -05:00
} ) ;
}
2015-09-14 18:59:09 -04:00
}
2016-07-18 06:50:31 -04:00
function getTransitiveModules (
module s : cpl . CompileNgModuleMetadata [ ] , includeImports : boolean ,
targetModules : cpl.CompileNgModuleMetadata [ ] = [ ] ,
2016-08-10 21:21:28 -04:00
visitedModules = new Set < Type < any > > ( ) ) : cpl . CompileNgModuleMetadata [ ] {
2016-07-18 06:50:31 -04:00
module s.forEach ( ( ngModule ) = > {
if ( ! visitedModules . has ( ngModule . type . runtime ) ) {
visitedModules . add ( ngModule . type . runtime ) ;
const nestedModules = includeImports ?
ngModule . importedModules . concat ( ngModule . exportedModules ) :
ngModule . exportedModules ;
getTransitiveModules ( nestedModules , includeImports , targetModules , visitedModules ) ;
// Add after recursing so imported/exported modules are before the module itself.
// This is important for overwriting providers of imported modules!
targetModules . push ( ngModule ) ;
}
} ) ;
return targetModules ;
2015-09-14 18:59:09 -04:00
}
2015-12-02 13:35:51 -05:00
2016-07-18 06:50:31 -04:00
function flattenArray ( tree : any [ ] , out : Array < any > = [ ] ) : Array < any > {
if ( tree ) {
for ( var i = 0 ; i < tree . length ; i ++ ) {
var item = resolveForwardRef ( tree [ i ] ) ;
if ( isArray ( item ) ) {
flattenArray ( item , out ) ;
} else {
out . push ( item ) ;
}
2015-09-14 18:59:09 -04:00
}
}
2016-06-22 17:06:23 -04:00
return out ;
2015-09-14 18:59:09 -04:00
}
2016-06-21 20:27:27 -04:00
function verifyNonBlankProviders (
2016-08-10 21:21:28 -04:00
directiveType : Type < any > , providersTree : any [ ] , providersType : string ) : any [ ] {
2016-06-21 20:27:27 -04:00
var flat : any [ ] = [ ] ;
var errMsg : string ;
flattenArray ( providersTree , flat ) ;
for ( var i = 0 ; i < flat . length ; i ++ ) {
if ( isBlank ( flat [ i ] ) ) {
errMsg = flat . map ( provider = > isBlank ( provider ) ? '?' : stringify ( provider ) ) . join ( ', ' ) ;
throw new BaseException (
` One or more of ${ providersType } for " ${ stringify ( directiveType ) } " were not defined: [ ${ errMsg } ]. ` ) ;
}
}
return providersTree ;
}
2016-02-18 13:53:21 -05:00
function isValidType ( value : any ) : boolean {
2016-06-28 12:54:42 -04:00
return cpl . isStaticSymbol ( value ) || ( value instanceof Type ) ;
2016-02-18 13:53:21 -05:00
}
function staticTypeModuleUrl ( value : any ) : string {
2016-06-28 12:54:42 -04:00
return cpl . isStaticSymbol ( value ) ? value.filePath : null ;
2015-09-14 18:59:09 -04:00
}
2016-06-08 19:38:52 -04:00
function componentModuleUrl (
reflector : ReflectorReader , type : any , cmpMetadata : ComponentMetadata ) : string {
2016-06-28 12:54:42 -04:00
if ( cpl . isStaticSymbol ( type ) ) {
2016-05-02 12:38:46 -04:00
return staticTypeModuleUrl ( type ) ;
2016-04-29 00:54:02 -04:00
}
if ( isPresent ( cmpMetadata . module Id ) ) {
var module Id = cmpMetadata . module Id ;
2015-12-05 05:21:38 -05:00
var scheme = getUrlScheme ( module Id ) ;
return isPresent ( scheme ) && scheme . length > 0 ? module Id :
2016-05-02 01:50:37 -04:00
` package: ${ module Id } ${ MODULE_SUFFIX } ` ;
2015-09-14 18:59:09 -04:00
}
2016-04-29 00:54:02 -04:00
return reflector . importUri ( type ) ;
2015-09-14 18:59:09 -04:00
}
2016-04-30 19:13:03 -04:00
2016-07-07 13:05:55 -04:00
function convertToCompileValue (
value : any , targetIdentifiers : cpl.CompileIdentifierMetadata [ ] ) : any {
return visitValue ( value , new _CompileValueConverter ( ) , targetIdentifiers ) ;
2016-04-30 19:13:03 -04:00
}
class _CompileValueConverter extends ValueTransformer {
2016-07-07 13:05:55 -04:00
visitOther ( value : any , targetIdentifiers : cpl.CompileIdentifierMetadata [ ] ) : any {
let identifier : cpl.CompileIdentifierMetadata ;
2016-06-28 12:54:42 -04:00
if ( cpl . isStaticSymbol ( value ) ) {
2016-07-07 13:05:55 -04:00
identifier = new cpl . CompileIdentifierMetadata (
{ name : value.name , module Url : value . filePath , runtime : value } ) ;
2016-04-30 19:13:03 -04:00
} else {
2016-07-07 13:05:55 -04:00
identifier = new cpl . CompileIdentifierMetadata ( { runtime : value } ) ;
2016-04-30 19:13:03 -04:00
}
2016-07-07 13:05:55 -04:00
targetIdentifiers . push ( identifier ) ;
return identifier ;
2016-04-30 19:13:03 -04:00
}
}