Skip to content

Commit 1d4d18d

Browse files
committed
refactor(render): user render compiler
1 parent 069bbf3 commit 1d4d18d

File tree

72 files changed

+1050
-4737
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

72 files changed

+1050
-4737
lines changed

modules/angular2/core.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@ export * from './src/core/annotations/di';
66

77
export * from './src/core/compiler/compiler';
88

9-
export * from './src/core/compiler/template_loader';
9+
// TODO(tbosch): remove this once render migration is complete
10+
export * from 'angular2/src/render/dom/compiler/template_loader';
1011
export * from './src/core/compiler/private_component_loader';
1112
export * from './src/core/compiler/private_component_location';
1213
export * from './src/core/compiler/view';
1314
export * from './src/core/compiler/view_container';
1415

1516
export * from './src/core/dom/element';
17+

modules/angular2/src/core/application.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@ import {ProtoView} from './compiler/view';
77
import {Reflector, reflector} from 'angular2/src/reflection/reflection';
88
import {Parser, Lexer, ChangeDetection, dynamicChangeDetection, jitChangeDetection} from 'angular2/change_detection';
99
import {ExceptionHandler} from './exception_handler';
10-
import {TemplateLoader} from './compiler/template_loader';
10+
import {TemplateLoader} from 'angular2/src/render/dom/compiler/template_loader';
1111
import {TemplateResolver} from './compiler/template_resolver';
1212
import {DirectiveMetadataReader} from './compiler/directive_metadata_reader';
13+
import {DirectiveBinding} from './compiler/element_injector';
1314
import {List, ListWrapper} from 'angular2/src/facade/collection';
1415
import {Promise, PromiseWrapper} from 'angular2/src/facade/async';
1516
import {VmTurnZone} from 'angular2/src/core/zone/vm_turn_zone';
@@ -24,7 +25,6 @@ import {ComponentUrlMapper} from 'angular2/src/core/compiler/component_url_mappe
2425
import {UrlResolver} from 'angular2/src/services/url_resolver';
2526
import {StyleUrlResolver} from 'angular2/src/render/dom/shadow_dom/style_url_resolver';
2627
import {StyleInliner} from 'angular2/src/render/dom/shadow_dom/style_inliner';
27-
import {CssProcessor} from 'angular2/src/core/compiler/css_processor';
2828
import {Component} from 'angular2/src/core/annotations/annotations';
2929
import {PrivateComponentLoader} from 'angular2/src/core/compiler/private_component_loader';
3030
import {TestabilityRegistry, Testability} from 'angular2/src/core/testability/testability';
@@ -74,7 +74,8 @@ function _injectorBindings(appComponentType): List<Binding> {
7474
return compiler.compile(appComponentAnnotatedType.type).then(
7575
(protoView) => {
7676
var appProtoView = ProtoView.createRootProtoView(protoView, appElement,
77-
appComponentAnnotatedType, changeDetection.createProtoChangeDetector('root'),
77+
DirectiveBinding.createFromType(appComponentAnnotatedType.type, appComponentAnnotatedType.annotation),
78+
changeDetection.createProtoChangeDetector('root'),
7879
strategy);
7980
// The light Dom of the app element is not considered part of
8081
// the angular application. Thus the context and lightDomInjector are
@@ -112,7 +113,6 @@ function _injectorBindings(appComponentType): List<Binding> {
112113
UrlResolver,
113114
StyleUrlResolver,
114115
StyleInliner,
115-
bind(CssProcessor).toFactory(() => new CssProcessor(null), []),
116116
PrivateComponentLoader,
117117
Testability,
118118
];

modules/angular2/src/core/compiler/compiler.js

Lines changed: 160 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,22 @@ import {List, ListWrapper, Map, MapWrapper} from 'angular2/src/facade/collection
66
import {ChangeDetection, Parser} from 'angular2/change_detection';
77

88
import {DirectiveMetadataReader} from './directive_metadata_reader';
9+
import {Component, Viewport, DynamicComponent, Decorator} from '../annotations/annotations';
910
import {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';
1412
import {TemplateResolver} from './template_resolver';
1513
import {Template} from '../annotations/template';
1614
import {ShadowDomStrategy} from './shadow_dom_strategy';
17-
import {CompileStep} from './pipeline/compile_step';
1815
import {ComponentUrlMapper} from './component_url_mapper';
16+
import {ProtoViewFactory} from './proto_view_factory';
1917
import {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

Comments
 (0)