@@ -11,8 +11,10 @@ import {CompilePipeline} from './pipeline/compile_pipeline';
1111import { CompileElement } from './pipeline/compile_element' ;
1212import { createDefaultSteps } from './pipeline/default_steps' ;
1313import { TemplateLoader } from './template_loader' ;
14+ import { TemplateResolver } from './template_resolver' ;
1415import { DirectiveMetadata } from './directive_metadata' ;
1516import { Component } from '../annotations/annotations' ;
17+ import { Template } from '../annotations/template' ;
1618import { Content } from './shadow_dom_emulation/content_tag' ;
1719import { ShadowDomStrategy } from './shadow_dom_strategy' ;
1820import { CompileStep } from './pipeline/compile_step' ;
@@ -55,13 +57,15 @@ export class Compiler {
5557 _compiling:Map < Type , Promise > ;
5658 _shadowDomStrategy: ShadowDomStrategy ;
5759 _shadowDomDirectives: List < DirectiveMetadata > ;
60+ _templateResolver: TemplateResolver ;
5861
5962 constructor ( changeDetection :ChangeDetection ,
6063 templateLoader :TemplateLoader ,
6164 reader : DirectiveMetadataReader ,
6265 parser :Parser ,
6366 cache :CompilerCache ,
64- shadowDomStrategy : ShadowDomStrategy ) {
67+ shadowDomStrategy : ShadowDomStrategy ,
68+ templateResolver : TemplateResolver ) {
6569 this . _changeDetection = changeDetection ;
6670 this . _reader = reader ;
6771 this . _parser = parser ;
@@ -74,63 +78,71 @@ export class Compiler {
7478 for ( var i = 0 ; i < types . length ; i ++ ) {
7579 ListWrapper . push ( this . _shadowDomDirectives , reader . read ( types [ i ] ) ) ;
7680 }
81+ this . _templateResolver = templateResolver ;
7782 }
7883
79- createSteps ( component :DirectiveMetadata ) :List < CompileStep > {
80- var directives = [ ]
81- var cmpDirectives = ListWrapper . map ( component . componentDirectives , ( d ) => this . _reader . read ( d ) ) ;
82- directives = ListWrapper . concat ( directives , cmpDirectives ) ;
83- directives = ListWrapper . concat ( directives , this . _shadowDomDirectives ) ;
84- return createDefaultSteps ( this . _changeDetection , this . _parser , component , directives ,
84+ createSteps ( component :Type , template : Template ) :List < CompileStep > {
85+ // Merge directive metadata (from the template and from the shadow dom strategy)
86+ var dirMetadata = [ ] ;
87+ var tplMetadata = ListWrapper . map ( this . _flattenDirectives ( template ) ,
88+ ( d ) => this . _reader . read ( d ) ) ;
89+ dirMetadata = ListWrapper . concat ( dirMetadata , tplMetadata ) ;
90+ dirMetadata = ListWrapper . concat ( dirMetadata , this . _shadowDomDirectives ) ;
91+
92+ var cmpMetadata = this . _reader . read ( component ) ;
93+
94+ return createDefaultSteps ( this . _changeDetection , this . _parser , cmpMetadata , dirMetadata ,
8595 this . _shadowDomStrategy ) ;
8696 }
8797
88- compile ( component :Type , templateRoot : Element = null ) :Promise < ProtoView > {
89- var protoView = this . _compile ( this . _reader . read ( component ) , templateRoot ) ;
98+ compile ( component : Type ) :Promise < ProtoView > {
99+ var protoView = this . _compile ( component ) ;
90100 return PromiseWrapper . isPromise ( protoView ) ? protoView : PromiseWrapper . resolve ( protoView ) ;
91101 }
92102
93103 // TODO(vicb): union type return ProtoView or Promise<ProtoView>
94- _compile ( cmpMetadata : DirectiveMetadata , templateRoot : Element = null ) {
95- var protoView = this . _compilerCache . get ( cmpMetadata . type ) ;
104+ _compile ( component : Type ) {
105+ var protoView = this . _compilerCache . get ( component ) ;
96106 if ( isPresent ( protoView ) ) {
97107 // The component has already been compiled into a ProtoView,
98108 // returns a resolved Promise.
99109 return protoView ;
100110 }
101111
102- var pvPromise = MapWrapper . get ( this . _compiling , cmpMetadata . type ) ;
112+ var pvPromise = MapWrapper . get ( this . _compiling , component ) ;
103113 if ( isPresent ( pvPromise ) ) {
104114 // The component is already being compiled, attach to the existing Promise
105115 // instead of re-compiling the component.
106116 // It happens when a template references a component multiple times.
107117 return pvPromise ;
108118 }
109119
110- var template = isBlank ( templateRoot ) ? this . _templateLoader . load ( cmpMetadata ) : templateRoot ;
120+ var template = this . _templateResolver . resolve ( component ) ;
111121
112- if ( PromiseWrapper . isPromise ( template ) ) {
113- pvPromise = PromiseWrapper . then ( template ,
114- ( el ) => this . _compileTemplate ( el , cmpMetadata ) ,
115- ( _ ) => { throw new BaseException ( `Failed to load the template for ${ stringify ( cmpMetadata . type ) } ` ) ; }
122+ var tplElement = this . _templateLoader . load ( template ) ;
123+
124+ if ( PromiseWrapper . isPromise ( tplElement ) ) {
125+ pvPromise = PromiseWrapper . then ( tplElement ,
126+ ( el ) => this . _compileTemplate ( template , el , component ) ,
127+ ( _ ) => { throw new BaseException ( `Failed to load the template for ${ stringify ( component ) } ` ) ; }
116128 ) ;
117- MapWrapper . set ( this . _compiling , cmpMetadata . type , pvPromise ) ;
129+ MapWrapper . set ( this . _compiling , component , pvPromise ) ;
118130 return pvPromise ;
119131 }
120132
121- return this . _compileTemplate ( template , cmpMetadata ) ;
133+ return this . _compileTemplate ( template , tplElement , component ) ;
122134 }
123135
124136 // TODO(vicb): union type return ProtoView or Promise<ProtoView>
125- _compileTemplate ( template : Element , cmpMetadata ) {
126- var pipeline = new CompilePipeline ( this . createSteps ( cmpMetadata ) ) ;
127- var compileElements = pipeline . process ( template ) ;
137+ _compileTemplate ( template : Template , tplElement : Element , component : Type ) {
138+ var pipeline = new CompilePipeline ( this . createSteps ( component , template ) ) ;
139+ var compileElements = pipeline . process ( tplElement ) ;
128140 var protoView = compileElements [ 0 ] . inheritedProtoView ;
129141
130142 // Populate the cache before compiling the nested components,
131143 // so that components can reference themselves in their template.
132- this . _compilerCache . set ( cmpMetadata . type , protoView ) ;
133- MapWrapper . delete ( this . _compiling , cmpMetadata . type ) ;
144+ this . _compilerCache . set ( component , protoView ) ;
145+ MapWrapper . delete ( this . _compiling , component ) ;
134146
135147 // Compile all the components from the template
136148 var nestedPVPromises = [ ] ;
@@ -146,17 +158,16 @@ export class Compiler {
146158 // The promise will resolved after nested ProtoViews are compiled.
147159 return PromiseWrapper . then ( PromiseWrapper . all ( nestedPVPromises ) ,
148160 ( _ ) => protoView ,
149- ( e ) => { throw new BaseException ( `${ e . message } -> Failed to compile ${ stringify ( cmpMetadata . type ) } ` ) ; }
161+ ( e ) => { throw new BaseException ( `${ e . message } -> Failed to compile ${ stringify ( component ) } ` ) ; }
150162 ) ;
151163 }
152164
153165 // When there is no asynchronous nested ProtoViews, return the ProtoView
154166 return protoView ;
155167 }
156168
157- _compileNestedProtoView ( ce : CompileElement , promises : List < Promise > )
158- {
159- var protoView = this . _compile ( ce . componentDirective ) ;
169+ _compileNestedProtoView ( ce : CompileElement , promises : List < Promise > ) {
170+ var protoView = this . _compile ( ce . componentDirective . type ) ;
160171
161172 if ( PromiseWrapper . isPromise ( protoView ) ) {
162173 ListWrapper . push ( promises , protoView ) ;
@@ -167,4 +178,27 @@ export class Compiler {
167178 ce. inheritedElementBinder . nestedProtoView = protoView ;
168179 }
169180 }
181+
182+ _flattenDirectives ( template : Template ) :List < Type > {
183+ if ( isBlank ( template . directives ) ) return [ ] ;
184+
185+ var directives = [ ] ;
186+ this . _flattenList ( template . directives , directives ) ;
187+
188+ return directives ;
189+ }
190+
191+ _flattenList ( tree :List < any > , out :List < Type > ) {
192+ for ( var i = 0 ; i < tree . length ; i ++ ) {
193+ var item = tree [ i ] ;
194+ if ( ListWrapper . isList ( item ) ) {
195+ this . _flattenList ( item , out ) ;
196+ } else {
197+ ListWrapper . push ( out , item ) ;
198+ }
199+ }
200+ }
201+
170202}
203+
204+
0 commit comments