@@ -6,18 +6,22 @@ import {List, ListWrapper, Map, MapWrapper} from 'angular2/src/facade/collection
66import { ChangeDetection , Parser } from 'angular2/change_detection' ;
77
88import { DirectiveMetadataReader } from './directive_metadata_reader' ;
9+ import { Component , Viewport , DynamicComponent , Decorator } from '../annotations/annotations' ;
910import { ProtoView } from './view' ;
10- import { CompilePipeline } from './pipeline/compile_pipeline' ;
11- import { CompileElement } from './pipeline/compile_element' ;
12- import { createDefaultSteps } from './pipeline/default_steps' ;
13- import { TemplateLoader } from './template_loader' ;
11+ import { DirectiveBinding } from './element_injector' ;
1412import { TemplateResolver } from './template_resolver' ;
1513import { Template } from '../annotations/template' ;
1614import { ShadowDomStrategy } from './shadow_dom_strategy' ;
17- import { CompileStep } from './pipeline/compile_step' ;
1815import { ComponentUrlMapper } from './component_url_mapper' ;
16+ import { ProtoViewFactory } from './proto_view_factory' ;
1917import { UrlResolver } from 'angular2/src/services/url_resolver' ;
20- import { CssProcessor } from './css_processor' ;
18+
19+ import { TemplateLoader } from 'angular2/src/render/dom/compiler/template_loader' ;
20+ import { DefaultStepFactory } from 'angular2/src/render/dom/compiler/compile_step_factory' ;
21+ import { DirectDomRenderer } from 'angular2/src/render/dom/direct_dom_renderer' ;
22+
23+ import * as rc from 'angular2/src/render/dom/compiler/compiler' ;
24+ import * as renderApi from 'angular2/src/render/api' ;
2125
2226/**
2327 * Cache that stores the ProtoView of the template of a component.
@@ -44,72 +48,51 @@ export class CompilerCache {
4448 }
4549}
4650
47- /**
48- * The compiler loads and translates the html templates of components into
49- * nested ProtoViews. To decompose its functionality it uses
50- * the CompilePipeline and the CompileSteps.
51- *
52- * @publicModule angular2/template
53- */
54- @Injectable ( )
55- export class Compiler {
51+
52+ // TODO(tbosch): rename this class to Compiler
53+ // and remove the current Compiler when core uses the render views.
54+ export class NewCompiler {
5655 _reader : DirectiveMetadataReader ;
57- _parser :Parser ;
5856 _compilerCache:CompilerCache ;
59- _changeDetection :ChangeDetection ;
60- _templateLoader :TemplateLoader ;
6157 _compiling:Map < Type , Promise > ;
62- _shadowDomStrategy : ShadowDomStrategy ;
6358 _templateResolver: TemplateResolver ;
6459 _componentUrlMapper: ComponentUrlMapper ;
6560 _urlResolver: UrlResolver ;
6661 _appUrl: string ;
67- _cssProcessor : CssProcessor ;
62+ _renderer: renderApi . Renderer ;
63+ _protoViewFactory:ProtoViewFactory ;
6864
69- constructor ( changeDetection :ChangeDetection ,
70- templateLoader :TemplateLoader ,
71- reader : DirectiveMetadataReader ,
72- parser :Parser ,
65+ constructor ( reader : DirectiveMetadataReader ,
7366 cache :CompilerCache ,
74- shadowDomStrategy : ShadowDomStrategy ,
7567 templateResolver : TemplateResolver ,
7668 componentUrlMapper : ComponentUrlMapper ,
7769 urlResolver : UrlResolver ,
78- cssProcessor : CssProcessor ) {
79- this . _changeDetection = changeDetection ;
70+ renderer : renderApi . Renderer ,
71+ protoViewFactory : ProtoViewFactory ) {
8072 this . _reader = reader ;
81- this . _parser = parser ;
8273 this . _compilerCache = cache ;
83- this . _templateLoader = templateLoader ;
8474 this . _compiling = MapWrapper . create ( ) ;
85- this . _shadowDomStrategy = shadowDomStrategy ;
8675 this . _templateResolver = templateResolver ;
8776 this . _componentUrlMapper = componentUrlMapper ;
8877 this . _urlResolver = urlResolver ;
8978 this . _appUrl = urlResolver . resolve ( null , './' ) ;
90- this . _cssProcessor = cssProcessor ;
79+ this . _renderer = renderer ;
80+ this . _protoViewFactory = protoViewFactory ;
9181 }
9282
93- // todo(misko): should be private method
94- createSteps ( component :Type , template : Template ) :List < CompileStep > {
95- var dirMetadata = ListWrapper . map ( this . _flattenDirectives ( template ) ,
96- ( d ) => this . _reader . read ( d ) ) ;
97-
98- var cmpMetadata = this . _reader . read ( component ) ;
99-
100- var templateUrl = this . _templateLoader . getTemplateUrl ( template ) ;
101-
102- return createDefaultSteps ( this . _changeDetection , this . _parser , cmpMetadata , dirMetadata ,
103- this . _shadowDomStrategy , templateUrl , this . _cssProcessor ) ;
83+ _bindDirective ( directive ) {
84+ var meta = this . _reader . read ( directive ) ;
85+ return DirectiveBinding . createFromType ( meta . type , meta . annotation ) ;
10486 }
10587
10688 compile ( component : Type ) :Promise < ProtoView > {
107- var protoView = this . _compile ( component ) ;
89+ var protoView = this . _compile ( this . _bindDirective ( component ) ) ;
10890 return PromiseWrapper . isPromise ( protoView ) ? protoView : PromiseWrapper . resolve ( protoView ) ;
10991 }
11092
11193 // TODO(vicb): union type return ProtoView or Promise<ProtoView>
112- _compile ( component : Type ) {
94+ _compile ( componentBinding : DirectiveBinding ) {
95+ var component = componentBinding . key . token ;
11396 var protoView = this . _compilerCache . get ( component ) ;
11497 if ( isPresent ( protoView ) ) {
11598 // The component has already been compiled into a ProtoView,
@@ -126,81 +109,112 @@ export class Compiler {
126109 }
127110
128111 var template = this . _templateResolver . resolve ( component ) ;
112+ var directives = ListWrapper . map (
113+ this . _flattenDirectives ( template ) ,
114+ ( directive ) => this . _bindDirective ( directive )
115+ ) ;
116+
117+ pvPromise = this . _compileNoRecurse ( componentBinding , template , directives ) . then ( ( protoView ) => {
118+ // Populate the cache before compiling the nested components,
119+ // so that components can reference themselves in their template.
120+ this . _compilerCache . set ( component , protoView ) ;
121+ MapWrapper . delete ( this . _compiling , component ) ;
122+
123+ // Compile all the components from the template
124+ var nestedPVPromises = this . _compileNestedComponents ( protoView ) ;
125+ if ( nestedPVPromises . length > 0 ) {
126+ // Returns ProtoView Promise when there are any asynchronous nested ProtoViews.
127+ // The promise will resolved after nested ProtoViews are compiled.
128+ return PromiseWrapper . then ( PromiseWrapper . all ( nestedPVPromises ) ,
129+ ( _ ) => protoView ,
130+ ( e ) => { throw new BaseException ( `${ e } -> Failed to compile ${ stringify ( component ) } ` ) ; }
131+ ) ;
132+ }
133+ return protoView ;
134+ } ) ;
135+ MapWrapper . set ( this . _compiling , component , pvPromise ) ;
136+ return pvPromise ;
137+ }
129138
130- var componentUrl = this . _componentUrlMapper . getUrl ( component ) ;
131- var baseUrl = this . _urlResolver . resolve ( this . _appUrl , componentUrl ) ;
132- this . _templateLoader . setBaseUrl ( template , baseUrl ) ;
133-
134- var tplElement = this . _templateLoader . load ( template ) ;
135-
136- if ( PromiseWrapper . isPromise ( tplElement ) ) {
137- pvPromise = PromiseWrapper . then ( tplElement ,
138- ( el ) => this . _compileTemplate ( template , el , component ) ,
139- ( _ ) => { throw new BaseException ( `Failed to load the template for ${ stringify ( component ) } ` ) ; }
140- ) ;
141- MapWrapper . set ( this . _compiling , component , pvPromise ) ;
142- return pvPromise ;
139+ _compileNoRecurse ( componentBinding , template , directives ) : Promise < ProtoView > {
140+ var component = componentBinding . key . token ;
141+ var componentUrl = this . _urlResolver . resolve (
142+ this . _appUrl , this . _componentUrlMapper . getUrl ( component )
143+ ) ;
144+ var templateAbsUrl = null ;
145+ if ( isPresent ( template . url ) ) {
146+ templateAbsUrl = this . _urlResolver . resolve ( componentUrl , template . url ) ;
147+ } else {
148+ // Note: If we have an inline template, we also need to send
149+ // the url for the component to the renderer so that it
150+ // is able to resolve urls in stylesheets.
151+ templateAbsUrl = componentUrl ;
143152 }
144-
145- return this . _compileTemplate ( template , tplElement , component ) ;
153+ var renderTemplate = new renderApi . Template ( {
154+ componentId : stringify ( component ) ,
155+ absUrl : templateAbsUrl ,
156+ inline : template . inline ,
157+ directives : ListWrapper . map ( directives , this . _buildRenderDirective )
158+ } ) ;
159+ return this . _renderer . compile ( renderTemplate ) . then ( ( renderPv ) => {
160+ return this . _protoViewFactory . createProtoView ( componentBinding . annotation , renderPv , directives ) ;
161+ } ) ;
146162 }
147163
148- // TODO(vicb): union type return ProtoView or Promise<ProtoView>
149- _compileTemplate ( template : Template , tplElement , component : Type ) {
150- var pipeline = new CompilePipeline ( this . createSteps ( component , template ) ) ;
151- var compileElements ;
152-
153- try {
154- compileElements = pipeline . process ( tplElement , stringify ( component ) ) ;
155- } catch ( ex ) {
156- return PromiseWrapper . reject ( ex ) ;
164+ _compileNestedComponents ( protoView , nestedPVPromises = null ) :List < Promise > {
165+ if ( isBlank ( nestedPVPromises ) ) {
166+ nestedPVPromises = [ ] ;
157167 }
158-
159- var protoView = compileElements [ 0 ] . inheritedProtoView ;
160-
161- // Populate the cache before compiling the nested components,
162- // so that components can reference themselves in their template.
163- this . _compilerCache . set ( component , protoView ) ;
164- MapWrapper . delete ( this . _compiling , component ) ;
165-
166- // Compile all the components from the template
167- var nestedPVPromises = [ ] ;
168- for ( var i = 0 ; i < compileElements . length ; i ++ ) {
169- var ce = compileElements [ i ] ;
170- if ( ce . hasNestedView ) {
171- this . _compileNestedProtoView ( ce , nestedPVPromises ) ;
168+ ListWrapper . map ( protoView . elementBinders , ( elementBinder ) => {
169+ var nestedComponent = elementBinder . componentDirective ;
170+ if ( isPresent ( nestedComponent ) && ! ( nestedComponent . annotation instanceof DynamicComponent ) ) {
171+ var nestedCall = this . _compile ( nestedComponent ) ;
172+ if ( PromiseWrapper . isPromise ( nestedCall ) ) {
173+ ListWrapper . push ( nestedPVPromises , nestedCall . then ( ( nestedPv ) => {
174+ elementBinder . nestedProtoView = nestedPv ;
175+ } ) ) ;
176+ } else {
177+ elementBinder . nestedProtoView = nestedCall ;
178+ }
179+ } else if ( isPresent ( elementBinder . nestedProtoView ) ) {
180+ this . _compileNestedComponents ( elementBinder . nestedProtoView , nestedPVPromises ) ;
172181 }
173- }
174-
175- if ( protoView . stylePromises . length > 0 ) {
176- // The protoView is ready after all asynchronous styles are ready
177- var syncProtoView = protoView ;
178- protoView = PromiseWrapper . all ( syncProtoView . stylePromises ) . then ( ( _ ) => syncProtoView ) ;
179- }
180-
181- if ( nestedPVPromises . length > 0 ) {
182- // Returns ProtoView Promise when there are any asynchronous nested ProtoViews.
183- // The promise will resolved after nested ProtoViews are compiled.
184- return PromiseWrapper . then ( PromiseWrapper . all ( nestedPVPromises ) ,
185- ( _ ) => protoView ,
186- ( e ) => { throw new BaseException ( `${ e . message } -> Failed to compile ${ stringify ( component ) } ` ) ; }
187- ) ;
188- }
189-
190- return protoView ;
182+ } ) ;
183+ return nestedPVPromises ;
191184 }
192185
193- _compileNestedProtoView ( ce : CompileElement , promises : List < Promise > ) {
194- var protoView = this . _compile ( ce . componentDirective . type ) ;
195-
196- if ( PromiseWrapper . isPromise ( protoView ) ) {
197- ListWrapper . push (
198- promises ,
199- protoView . then ( function ( pv ) { ce . inheritedElementBinder . nestedProtoView = pv ; } )
200- ) ;
201- } else {
202- ce . inheritedElementBinder . nestedProtoView = protoView ;
186+ _buildRenderDirective ( directiveBinding ) {
187+ var ann = directiveBinding . annotation ;
188+ var renderType ;
189+ var compileChildren = true ;
190+ if ( ( ann instanceof Component ) || ( ann instanceof DynamicComponent ) ) {
191+ renderType = renderApi . DirectiveMetadata . COMPONENT_TYPE ;
192+ } else if ( ann instanceof Viewport ) {
193+ renderType = renderApi . DirectiveMetadata . VIEWPORT_TYPE ;
194+ } else if ( ann instanceof Decorator ) {
195+ renderType = renderApi . DirectiveMetadata . DECORATOR_TYPE ;
196+ compileChildren = ann . compileChildren ;
203197 }
198+ var setters = [ ] ;
199+ var readAttributes = [ ] ;
200+ ListWrapper . forEach ( directiveBinding . dependencies , ( dep ) => {
201+ if ( isPresent ( dep . propSetterName ) ) {
202+ ListWrapper . push ( setters , dep . propSetterName ) ;
203+ }
204+ if ( isPresent ( dep . attributeName ) ) {
205+ ListWrapper . push ( readAttributes , dep . attributeName ) ;
206+ }
207+ } ) ;
208+ return new renderApi . DirectiveMetadata ( {
209+ id : stringify ( directiveBinding . key . token ) ,
210+ type : renderType ,
211+ selector : ann . selector ,
212+ compileChildren : compileChildren ,
213+ events : isPresent ( ann . events ) ? MapWrapper . createFromStringMap ( ann . events ) : null ,
214+ bind : isPresent ( ann . bind ) ? MapWrapper . createFromStringMap ( ann . bind ) : null ,
215+ setters : setters ,
216+ readAttributes : readAttributes
217+ } ) ;
204218 }
205219
206220 _flattenDirectives ( template : Template ) :List < Type > {
@@ -225,4 +239,39 @@ export class Compiler {
225239
226240}
227241
228-
242+ // TODO(tbosch): delete this class once we use the render views
243+ /**
244+ * The compiler loads and translates the html templates of components into
245+ * nested ProtoViews. To decompose its functionality it uses
246+ * the render compiler.
247+ *
248+ * @publicModule angular2/template
249+ */
250+ @Injectable ( )
251+ export class Compiler extends NewCompiler {
252+ constructor ( changeDetection :ChangeDetection ,
253+ templateLoader :TemplateLoader ,
254+ reader : DirectiveMetadataReader ,
255+ parser :Parser ,
256+ cache :CompilerCache ,
257+ shadowDomStrategy : ShadowDomStrategy ,
258+ templateResolver : TemplateResolver ,
259+ componentUrlMapper : ComponentUrlMapper ,
260+ urlResolver : UrlResolver ) {
261+ super (
262+ reader ,
263+ cache ,
264+ templateResolver ,
265+ componentUrlMapper ,
266+ urlResolver ,
267+ new DirectDomRenderer (
268+ new rc . Compiler (
269+ new DefaultStepFactory ( parser , shadowDomStrategy . render ) ,
270+ templateLoader
271+ ) ,
272+ null , null
273+ ) ,
274+ new ProtoViewFactory ( changeDetection , shadowDomStrategy )
275+ ) ;
276+ }
277+ }
0 commit comments