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-09-12 22:14:17 -04:00
import { AnimationAnimateMetadata , AnimationEntryMetadata , AnimationGroupMetadata , AnimationKeyframesSequenceMetadata , AnimationMetadata , AnimationStateDeclarationMetadata , AnimationStateMetadata , AnimationStateTransitionMetadata , AnimationStyleMetadata , AnimationWithStepsMetadata , Attribute , ChangeDetectionStrategy , Component , Host , Inject , Injectable , ModuleWithProviders , Optional , Provider , Query , SchemaMetadata , Self , SkipSelf , Type , resolveForwardRef } from '@angular/core' ;
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' ;
import { DirectiveResolver } from './directive_resolver' ;
2016-09-14 18:58:18 -04:00
import { isBlank , isPresent , isString , stringify } from './facade/lang' ;
2016-08-24 20:39:49 -04:00
import { Identifiers , resolveIdentifierToken } 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-08-30 21:07:40 -04:00
import { LIFECYCLE_HOOKS_VALUES , ReflectorReader , reflector } from './private_import_core' ;
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-08-19 16:51:45 -04:00
private _pipeResolver : PipeResolver , private _schemaRegistry : ElementSchemaRegistry ,
2016-07-29 05:10:30 -04:00
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 ) ;
2016-09-14 18:58:18 -04:00
if ( ! found ) {
2016-04-20 21:10:19 -04:00
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 ) ;
2016-09-12 22:14:17 -04:00
// Clear all of the NgModule as they contain transitive information!
2016-07-18 06:50:31 -04:00
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-09-14 18:58:18 -04:00
const defs = entry . definitions . map ( def = > this . getAnimationStateMetadata ( def ) ) ;
2016-05-25 15:46:22 -04:00
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-09-14 18:58:18 -04:00
const styles = this . getAnimationStyleMetadata ( value . styles ) ;
2016-05-25 15:46:22 -04:00
return new cpl . CompileAnimationStateDeclarationMetadata ( value . stateNameExpr , styles ) ;
2016-09-14 18:58:18 -04:00
}
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
}
2016-09-14 18:58:18 -04:00
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-09-14 18:58:18 -04:00
}
if ( value instanceof AnimationKeyframesSequenceMetadata ) {
2016-06-08 19:38:52 -04:00
return new cpl . CompileAnimationKeyframesSequenceMetadata (
value . steps . map ( entry = > this . getAnimationStyleMetadata ( entry ) ) ) ;
2016-09-14 18:58:18 -04:00
}
if ( value instanceof AnimationAnimateMetadata ) {
const animateData =
2016-06-08 19:38:52 -04:00
< cpl.CompileAnimationStyleMetadata | cpl.CompileAnimationKeyframesSequenceMetadata > this
. getAnimationMetadata ( value . styles ) ;
2016-05-25 15:46:22 -04:00
return new cpl . CompileAnimationAnimateMetadata ( value . timings , animateData ) ;
2016-09-14 18:58:18 -04:00
}
if ( value instanceof AnimationWithStepsMetadata ) {
const 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 ) ;
}
2016-09-14 18:58:18 -04:00
return new cpl . CompileAnimationSequenceMetadata ( steps ) ;
2016-05-25 15:46:22 -04:00
}
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 ) ;
2016-09-14 18:58:18 -04:00
let meta = this . _directiveCache . get ( directiveType ) ;
if ( ! meta ) {
const dirMeta = this . _directiveResolver . resolve ( directiveType , throwIfNotFound ) ;
2016-07-18 06:50:31 -04:00
if ( ! dirMeta ) {
return null ;
}
2016-09-14 18:58:18 -04:00
let templateMeta : cpl.CompileTemplateMetadata = null ;
let changeDetectionStrategy : ChangeDetectionStrategy = null ;
let viewProviders : Array < cpl.CompileProviderMetadata | cpl.CompileTypeMetadata | any [ ] > = [ ] ;
let module Url = staticTypeModuleUrl ( directiveType ) ;
let entryComponentMetadata : cpl.CompileTypeMetadata [ ] = [ ] ;
2016-07-28 13:39:10 -04:00
let selector = dirMeta . selector ;
2016-09-14 18:58:18 -04:00
2016-09-12 22:14:17 -04:00
if ( dirMeta instanceof Component ) {
2016-09-14 18:58:18 -04:00
// Component
assertArrayOfStrings ( 'styles' , dirMeta . styles ) ;
assertArrayOfStrings ( 'styleUrls' , dirMeta . styleUrls ) ;
assertInterpolationSymbols ( 'interpolation' , dirMeta . interpolation ) ;
const animations = dirMeta . animations ?
dirMeta . animations . map ( e = > this . getAnimationEntryMetadata ( e ) ) :
2016-06-08 19:38:52 -04:00
null ;
2016-05-25 15:46:22 -04:00
2015-09-18 13:33:23 -04:00
templateMeta = new cpl . CompileTemplateMetadata ( {
2016-09-14 18:58:18 -04:00
encapsulation : dirMeta.encapsulation ,
template : dirMeta.template ,
templateUrl : dirMeta.templateUrl ,
styles : dirMeta.styles ,
styleUrls : dirMeta.styleUrls ,
2016-06-20 12:52:41 -04:00
animations : animations ,
2016-09-14 18:58:18 -04:00
interpolation : dirMeta.interpolation
2015-09-14 18:59:09 -04:00
} ) ;
2016-09-14 18:58:18 -04:00
changeDetectionStrategy = dirMeta . changeDetection ;
if ( dirMeta . viewProviders ) {
2016-06-21 20:27:27 -04:00
viewProviders = this . getProvidersMetadata (
2016-08-23 19:18:41 -04:00
dirMeta . viewProviders , entryComponentMetadata ,
` viewProviders for " ${ stringify ( directiveType ) } " ` ) ;
2016-01-06 17:13:44 -05:00
}
2016-09-14 18:58:18 -04:00
module Url = componentModuleUrl ( this . _reflector , directiveType , dirMeta ) ;
if ( dirMeta . entryComponents ) {
2016-08-19 16:51:45 -04:00
entryComponentMetadata =
2016-09-14 18:58:18 -04:00
flattenArray ( dirMeta . entryComponents )
2016-08-19 16:51:45 -04:00
. map ( ( type ) = > this . getTypeMetadata ( type , staticTypeModuleUrl ( type ) ) )
. concat ( entryComponentMetadata ) ;
2016-06-22 17:06:23 -04:00
}
2016-07-28 13:39:10 -04:00
if ( ! selector ) {
selector = this . _schemaRegistry . getDefaultComponentElementName ( ) ;
}
} else {
2016-09-14 18:58:18 -04:00
// Directive
2016-07-28 13:39:10 -04:00
if ( ! selector ) {
2016-08-25 03:50:16 -04:00
throw new Error ( ` Directive ${ stringify ( directiveType ) } has no selector, please add it! ` ) ;
2016-07-28 13:39:10 -04:00
}
2016-01-06 17:13:44 -05:00
}
2016-09-14 18:58:18 -04:00
let 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-08-23 19:18:41 -04:00
dirMeta . providers , entryComponentMetadata ,
` providers for " ${ stringify ( directiveType ) } " ` ) ;
2016-01-06 17:13:44 -05:00
}
2016-09-14 18:58:18 -04:00
let queries : cpl.CompileQueryMetadata [ ] = [ ] ;
let 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
}
2016-09-14 18:58:18 -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 ,
2016-09-14 18:58:18 -04:00
isComponent : ! ! 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-08-19 16:51:45 -04:00
entryComponents : entryComponentMetadata
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-09-14 18:58:18 -04:00
let compileMeta = this . _ngModuleCache . get ( module Type ) ;
2016-07-18 06:50:31 -04:00
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 ) {
2016-08-23 19:18:41 -04:00
providers . push ( . . . this . getProvidersMetadata (
module WithProviders.providers , entryComponents ,
` provider for the NgModule ' ${ stringify ( importedModuleType ) } ' ` ) ) ;
2016-07-25 04:39:50 -04:00
}
2016-07-18 06:50:31 -04:00
}
2016-09-14 18:58:18 -04:00
2016-07-25 04:39:50 -04:00
if ( importedModuleType ) {
2016-09-14 18:58:18 -04:00
const importedMeta = this . getNgModuleMetadata ( importedModuleType , false ) ;
2016-08-17 18:57:02 -04:00
if ( importedMeta === null ) {
2016-08-25 03:50:16 -04:00
throw new Error (
2016-08-17 18:57:02 -04:00
` 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 {
2016-08-25 03:50:16 -04:00
throw new Error (
2016-07-18 06:50:31 -04:00
` Unexpected value ' ${ stringify ( importedType ) } ' imported by the module ' ${ stringify ( module Type ) } ' ` ) ;
}
} ) ;
}
if ( meta . exports ) {
flattenArray ( meta . exports ) . forEach ( ( exportedType ) = > {
if ( ! isValidType ( exportedType ) ) {
2016-08-25 03:50:16 -04:00
throw new Error (
2016-07-18 06:50:31 -04:00
` 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 {
2016-08-25 03:50:16 -04:00
throw new Error (
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 ) ) {
2016-08-25 03:50:16 -04:00
throw new Error (
2016-07-18 06:50:31 -04:00
` 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 {
2016-08-25 03:50:16 -04:00
throw new Error (
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 ) {
2016-08-23 19:18:41 -04:00
providers . push ( . . . this . getProvidersMetadata (
meta . providers , entryComponents ,
` provider for the NgModule ' ${ stringify ( module Type ) } ' ` ) ) ;
2016-07-27 04:52:31 -04:00
}
2016-09-14 18:58:18 -04:00
2016-07-27 04:52:31 -04:00
if ( meta . entryComponents ) {
entryComponents . push (
. . . flattenArray ( meta . entryComponents )
. map ( type = > this . getTypeMetadata ( type , staticTypeModuleUrl ( type ) ) ) ) ;
}
2016-09-14 18:58:18 -04:00
2016-08-02 09:54:08 -04:00
if ( meta . bootstrap ) {
2016-09-06 12:55:48 -04:00
const typeMetadata = flattenArray ( meta . bootstrap ) . map ( type = > {
if ( ! isValidType ( type ) ) {
throw new Error (
` Unexpected value ' ${ stringify ( type ) } ' used in the bootstrap property of module ' ${ stringify ( module Type ) } ' ` ) ;
}
return this . getTypeMetadata ( type , staticTypeModuleUrl ( type ) ) ;
} ) ;
bootstrapComponents . push ( . . . typeMetadata ) ;
2016-08-02 09:54:08 -04:00
}
2016-09-14 18:58:18 -04:00
2016-08-02 09:54:08 -04:00
entryComponents . push ( . . . bootstrapComponents ) ;
2016-09-14 18:58:18 -04:00
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 ) ) ,
2016-09-14 18:58:18 -04:00
providers ,
entryComponents ,
bootstrapComponents ,
schemas ,
declaredDirectives ,
exportedDirectives ,
declaredPipes ,
exportedPipes ,
importedModules ,
exportedModules ,
transitiveModule ,
2016-09-01 16:46:08 -04:00
id : meta.id ,
2016-06-28 12:54:42 -04:00
} ) ;
2016-09-14 18:58:18 -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-07-18 06:50:31 -04:00
private _verifyModule ( module Meta : cpl . CompileNgModuleMetadata ) {
module Meta.exportedDirectives.forEach ( ( dirMeta ) = > {
2016-08-29 11:52:25 -04:00
if ( ! module Meta.transitiveModule.directivesSet.has ( dirMeta . type . reference ) ) {
2016-08-25 03:50:16 -04:00
throw new Error (
2016-08-29 11:52:25 -04:00
` Can't export directive ${ stringify ( dirMeta . type . reference ) } from ${ stringify ( module Meta.type.reference ) } as it was neither declared nor imported! ` ) ;
2016-07-18 06:50:31 -04:00
}
} ) ;
2016-09-14 18:58:18 -04:00
2016-07-18 06:50:31 -04:00
module Meta.exportedPipes.forEach ( ( pipeMeta ) = > {
2016-08-29 11:52:25 -04:00
if ( ! module Meta.transitiveModule.pipesSet.has ( pipeMeta . type . reference ) ) {
2016-08-25 03:50:16 -04:00
throw new Error (
2016-08-29 11:52:25 -04:00
` Can't export pipe ${ stringify ( pipeMeta . type . reference ) } from ${ stringify ( module Meta.type.reference ) } as it was neither declared nor imported! ` ) ;
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' ;
2016-09-14 18:58:18 -04:00
}
if ( this . _pipeResolver . resolve ( type , false ) !== null ) {
2016-08-17 18:57:02 -04:00
return 'pipe' ;
2016-09-14 18:58:18 -04:00
}
if ( this . _ngModuleResolver . resolve ( type , false ) !== null ) {
2016-08-17 18:57:02 -04:00
return 'module' ;
2016-09-14 18:58:18 -04:00
}
if ( ( type as any ) . provide ) {
2016-08-17 18:57:02 -04:00
return 'provider' ;
}
2016-09-14 18:58:18 -04:00
return 'value' ;
2016-08-17 18:57:02 -04:00
}
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 ) {
2016-08-25 03:50:16 -04:00
throw new Error (
2016-09-07 17:09:25 -04:00
` Type ${ stringify ( type ) } is part of the declarations of 2 modules: ${ stringify ( oldModule ) } and ${ stringify ( module Type ) } ! ` +
` Please consider moving ${ stringify ( type ) } to a higher module that imports ${ stringify ( oldModule ) } and ${ stringify ( module Type ) } . ` +
` You can also create a new NgModule that exports and includes ${ stringify ( type ) } then import that NgModule in ${ 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 _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 {
2016-08-29 11:52:25 -04:00
if ( force || ! transitiveModule . directivesSet . has ( dirMeta . type . reference ) ) {
transitiveModule . directivesSet . add ( dirMeta . type . reference ) ;
2016-07-18 06:50:31 -04:00
transitiveModule . directives . push ( dirMeta ) ;
declaredDirectives . push ( dirMeta ) ;
2016-08-29 11:52:25 -04:00
this . _addTypeToModule ( dirMeta . type . reference , module Type ) ;
2016-07-18 06:50:31 -04:00
return true ;
}
return false ;
}
private _addPipeToModule (
pipeMeta : cpl.CompilePipeMetadata , module Type : any ,
transitiveModule : cpl.TransitiveCompileNgModuleMetadata ,
declaredPipes : cpl.CompilePipeMetadata [ ] , force : boolean = false ) : boolean {
2016-08-29 11:52:25 -04:00
if ( force || ! transitiveModule . pipesSet . has ( pipeMeta . type . reference ) ) {
transitiveModule . pipesSet . add ( pipeMeta . type . reference ) ;
2016-07-18 06:50:31 -04:00
transitiveModule . pipes . push ( pipeMeta ) ;
declaredPipes . push ( pipeMeta ) ;
2016-08-29 11:52:25 -04:00
this . _addTypeToModule ( pipeMeta . type . reference , module Type ) ;
2016-07-18 06:50:31 -04:00
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-09-14 18:58:18 -04:00
module Url ,
2016-08-29 11:52:25 -04:00
reference : 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-09-14 18:58:18 -04:00
module Url ,
2016-08-29 11:52:25 -04:00
reference : 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 ) ;
2016-09-14 18:58:18 -04:00
let meta = this . _pipeCache . get ( pipeType ) ;
if ( ! meta ) {
const pipeMeta = this . _pipeResolver . resolve ( pipeType , throwIfNotFound ) ;
2016-07-18 06:50:31 -04:00
if ( ! pipeMeta ) {
return null ;
}
2016-09-14 18:58:18 -04:00
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-09-14 18:58:18 -04:00
let params = dependencies || this . _reflector . parameters ( typeOrFunc ) || [ ] ;
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-09-12 22:14:17 -04:00
let query : Query = null ;
let viewQuery : Query = null ;
2016-06-17 13:57:50 -04:00
var token : any = null ;
2016-09-14 18:58:18 -04:00
if ( Array . isArray ( param ) ) {
param . forEach ( ( paramEntry ) = > {
2016-09-12 22:14:17 -04:00
if ( paramEntry instanceof Host ) {
2016-06-08 19:38:52 -04:00
isHost = true ;
2016-09-12 22:14:17 -04:00
} else if ( paramEntry instanceof Self ) {
2016-06-08 19:38:52 -04:00
isSelf = true ;
2016-09-12 22:14:17 -04:00
} else if ( paramEntry instanceof SkipSelf ) {
2016-06-08 19:38:52 -04:00
isSkipSelf = true ;
2016-09-12 22:14:17 -04:00
} else if ( paramEntry instanceof Optional ) {
2016-06-08 19:38:52 -04:00
isOptional = true ;
2016-09-12 22:14:17 -04:00
} else if ( paramEntry instanceof Attribute ) {
2016-06-08 19:38:52 -04:00
isAttribute = true ;
token = paramEntry . attributeName ;
2016-09-12 22:14:17 -04:00
} else if ( paramEntry instanceof Query ) {
2016-06-08 19:38:52 -04:00
if ( paramEntry . isViewQuery ) {
viewQuery = paramEntry ;
} else {
query = paramEntry ;
}
2016-09-12 22:14:17 -04:00
} else if ( paramEntry instanceof Inject ) {
2016-06-08 19:38:52 -04:00
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
}
2016-09-14 18:58:18 -04:00
2016-01-06 17:13:44 -05:00
return new cpl . CompileDiDependencyMetadata ( {
2016-09-14 18:58:18 -04:00
isAttribute ,
isHost ,
isSelf ,
isSkipSelf ,
isOptional ,
query : query ? this . getQueryMetadata ( query , null , typeOrFunc ) : null ,
viewQuery : 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 =
2016-09-14 18:58:18 -04:00
dependenciesMetadata . map ( ( dep ) = > dep ? stringify ( dep . token ) : '?' ) . join ( ', ' ) ;
2016-08-25 03:50:16 -04:00
throw new Error (
2016-06-08 19:38:52 -04:00
` 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-09-14 18:58:18 -04:00
let compileToken : cpl.CompileTokenMetadata ;
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 ( {
2016-08-29 11:52:25 -04:00
reference : token ,
2016-02-18 13:53:21 -05:00
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-23 19:18:41 -04:00
getProvidersMetadata (
providers : Provider [ ] , targetEntryComponents : cpl.CompileTypeMetadata [ ] ,
debugInfo? : string ) : Array < cpl.CompileProviderMetadata | cpl.CompileTypeMetadata | any [ ] > {
2016-07-07 13:05:55 -04:00
const compileProviders : Array < cpl.CompileProviderMetadata | cpl.CompileTypeMetadata | any [ ] > = [ ] ;
2016-08-23 19:18:41 -04:00
providers . forEach ( ( provider : any , providerIdx : number ) = > {
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-09-14 18:58:18 -04:00
if ( Array . isArray ( provider ) ) {
2016-08-23 19:18:41 -04:00
compileProvider = this . getProvidersMetadata ( provider , targetEntryComponents , debugInfo ) ;
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-08-29 11:52:25 -04:00
if ( tokenMeta . reference ===
resolveIdentifierToken ( Identifiers . ANALYZE_FOR_ENTRY_COMPONENTS ) . reference ) {
2016-07-25 03:36:30 -04:00
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 {
2016-08-23 19:18:41 -04:00
let providersInfo = ( < string [ ] > providers . reduce (
( soFar : string [ ] , seenProvider : any , seenProviderIdx : number ) = > {
if ( seenProviderIdx < providerIdx ) {
soFar . push ( ` ${ stringify ( seenProvider ) } ` ) ;
} else if ( seenProviderIdx == providerIdx ) {
soFar . push ( ` ? ${ stringify ( seenProvider ) } ? ` ) ;
} else if ( seenProviderIdx == providerIdx + 1 ) {
soFar . push ( '...' ) ;
}
return soFar ;
} ,
[ ] ) )
. join ( ', ' ) ;
2016-08-25 03:50:16 -04:00
throw new Error (
2016-08-23 19:18:41 -04:00
` Invalid ${ debugInfo ? debugInfo : 'provider' } - only instances of Provider and Type are allowed, got: [ ${ providersInfo } ] ` ) ;
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-09-14 18:58:18 -04:00
const components : cpl.CompileTypeMetadata [ ] = [ ] ;
const collectedIdentifiers : cpl.CompileIdentifierMetadata [ ] = [ ] ;
2016-07-07 13:05:55 -04:00
if ( provider . useFactory || provider . useExisting || provider . useClass ) {
2016-08-25 03:50:16 -04:00
throw new Error ( ` The ANALYZE_FOR_ENTRY_COMPONENTS token only supports useValue! ` ) ;
2016-07-07 13:05:55 -04:00
}
2016-09-14 18:58:18 -04:00
2016-07-07 13:05:55 -04:00
if ( ! provider . multi ) {
2016-08-25 03:50:16 -04:00
throw new Error ( ` The ANALYZE_FOR_ENTRY_COMPONENTS token only supports 'multi = true'! ` ) ;
2016-07-07 13:05:55 -04:00
}
2016-09-14 18:58:18 -04:00
2016-07-07 13:05:55 -04:00
convertToCompileValue ( provider . useValue , collectedIdentifiers ) ;
collectedIdentifiers . forEach ( ( identifier ) = > {
2016-09-14 18:58:18 -04:00
const dirMeta = this . getDirectiveMetadata ( identifier . reference , 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-09-14 18:58:18 -04:00
let compileDeps : cpl.CompileDiDependencyMetadata [ ] ;
let compileTypeMetadata : cpl.CompileTypeMetadata = null ;
let compileFactoryMetadata : cpl.CompileFactoryMetadata = null ;
2016-06-18 12:42:34 -04:00
2016-09-14 18:58:18 -04:00
if ( provider . useClass ) {
2016-06-18 12:42:34 -04:00
compileTypeMetadata = this . getTypeMetadata (
provider . useClass , staticTypeModuleUrl ( provider . useClass ) , provider . dependencies ) ;
compileDeps = compileTypeMetadata . diDeps ;
2016-09-14 18:58:18 -04:00
} else if ( 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-09-14 18:58:18 -04:00
useExisting : provider.useExisting ? this . getTokenMetadata ( provider . useExisting ) : null ,
2016-01-06 17:13:44 -05:00
deps : compileDeps ,
multi : provider.multi
} ) ;
}
2016-06-08 19:38:52 -04:00
getQueriesMetadata (
2016-09-12 22:14:17 -04:00
queries : { [ key : string ] : Query } , isViewQuery : boolean ,
2016-08-10 21:21:28 -04:00
directiveType : Type < any > ) : cpl . CompileQueryMetadata [ ] {
2016-09-14 18:58:18 -04:00
const res : cpl.CompileQueryMetadata [ ] = [ ] ;
Object . keys ( queries ) . forEach ( ( propertyName : string ) = > {
const query = queries [ propertyName ] ;
2016-06-22 20:25:42 -04:00
if ( query . isViewQuery === isViewQuery ) {
res . push ( this . getQueryMetadata ( query , propertyName , directiveType ) ) ;
}
} ) ;
2016-01-06 17:13:44 -05:00
2016-09-14 18:58:18 -04:00
return res ;
2016-09-12 12:44:20 -04:00
}
2016-09-14 18:58:18 -04:00
private _queryVarBindings ( selector : any ) : string [ ] { return selector . split ( /\s*,\s*/ ) ; }
2016-09-12 12:44:20 -04:00
2016-09-12 22:14:17 -04:00
getQueryMetadata ( q : Query , 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-09-14 18:58:18 -04:00
if ( typeof q . selector === 'string' ) {
2016-09-12 12:44:20 -04:00
selectors = this . _queryVarBindings ( q . selector ) . map ( varName = > this . getTokenMetadata ( varName ) ) ;
2016-01-06 17:13:44 -05:00
} else {
2016-09-14 18:58:18 -04:00
if ( ! q . selector ) {
2016-08-25 03:50:16 -04:00
throw new Error (
2016-06-08 19:38:52 -04:00
` 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 ) ] ;
}
2016-09-14 18:58:18 -04:00
2016-01-06 17:13:44 -05:00
return new cpl . CompileQueryMetadata ( {
2016-09-14 18:58:18 -04:00
selectors ,
2016-01-06 17:13:44 -05:00
first : q.first ,
2016-09-14 18:58:18 -04:00
descendants : q.descendants , propertyName ,
read : 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 ) = > {
2016-08-29 11:52:25 -04:00
if ( ! visitedModules . has ( ngModule . type . reference ) ) {
visitedModules . add ( ngModule . type . reference ) ;
2016-07-18 06:50:31 -04:00
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 ) {
2016-09-14 18:58:18 -04:00
for ( let i = 0 ; i < tree . length ; i ++ ) {
const item = resolveForwardRef ( tree [ i ] ) ;
if ( Array . isArray ( item ) ) {
2016-07-18 06:50:31 -04:00
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-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-09-14 19:49:13 -04:00
function componentModuleUrl (
reflector : ReflectorReader , type : Type < any > , cmpMetadata : Component ) : 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
}
2016-09-14 19:49:13 -04:00
const module Id = cmpMetadata . module Id ;
if ( typeof module Id === 'string' ) {
2016-09-14 18:58:18 -04:00
const scheme = getUrlScheme ( module Id ) ;
return scheme ? module Id : ` package: ${ module Id } ${ MODULE_SUFFIX } ` ;
2016-09-14 19:49:13 -04:00
} else if ( module Id !== null && module Id !== void 0 ) {
throw new Error (
` moduleId should be a string in " ${ stringify ( type ) } ". See https://goo.gl/wIDDiL for more information. \ n ` +
` If you're using Webpack you should inline the template and the styles, see https://goo.gl/X2J8zc. ` ) ;
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 (
2016-08-29 11:52:25 -04:00
{ name : value.name , module Url : value . filePath , reference : value } ) ;
2016-04-30 19:13:03 -04:00
} else {
2016-08-29 11:52:25 -04:00
identifier = new cpl . CompileIdentifierMetadata ( { reference : 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
}
}