Skip to content

Commit 5009876

Browse files
committed
refactor(render): use render layer fully
Introduces angular2/src/core/compiler/ViewFactory which extracts ProtoView.instantiate and replaces ViewPool. Note: This is a work in progress commit to unblock other commits. There will be follow ups to add unit tests, remove TODOs, …
1 parent de581ea commit 5009876

Some content is hidden

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

60 files changed

+1205
-3340
lines changed

karma-dart.conf.js

+2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ module.exports = function(config) {
88
frameworks: ['dart-unittest'],
99

1010
files: [
11+
// Init and configure guiness.
12+
{pattern: 'test-init.dart', included: true},
1113
// Unit test files needs to be included.
1214
// Karma-dart generates `__adapter_unittest.dart` that imports these files.
1315
{pattern: 'modules/*/test/**/*_spec.js', included: true},

modules/angular2/core.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,5 @@ export * from './src/core/compiler/private_component_location';
1414
export * from './src/core/compiler/view';
1515
export * from './src/core/compiler/view_container';
1616

17-
export * from './src/core/dom/element';
17+
export * from './src/core/compiler/ng_element';
1818

modules/angular2/src/core/application.js

+31-7
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@ import {ExceptionHandler} from './exception_handler';
99
import {TemplateLoader} from 'angular2/src/render/dom/compiler/template_loader';
1010
import {TemplateResolver} from './compiler/template_resolver';
1111
import {DirectiveMetadataReader} from './compiler/directive_metadata_reader';
12-
import {DirectiveBinding} from './compiler/element_injector';
1312
import {List, ListWrapper} from 'angular2/src/facade/collection';
1413
import {Promise, PromiseWrapper} from 'angular2/src/facade/async';
1514
import {VmTurnZone} from 'angular2/src/core/zone/vm_turn_zone';
1615
import {LifeCycle} from 'angular2/src/core/life_cycle/life_cycle';
17-
import {ShadowDomStrategy, NativeShadowDomStrategy, EmulatedUnscopedShadowDomStrategy} from 'angular2/src/core/compiler/shadow_dom_strategy';
16+
import {ShadowDomStrategy} from 'angular2/src/render/dom/shadow_dom/shadow_dom_strategy';
17+
import {EmulatedUnscopedShadowDomStrategy} from 'angular2/src/render/dom/shadow_dom/emulated_unscoped_shadow_dom_strategy';
1818
import {XHR} from 'angular2/src/services/xhr';
1919
import {XHRImpl} from 'angular2/src/services/xhr_impl';
2020
import {EventManager, DomEventsPlugin} from 'angular2/src/render/dom/events/event_manager';
@@ -27,6 +27,13 @@ import {StyleInliner} from 'angular2/src/render/dom/shadow_dom/style_inliner';
2727
import {Component} from 'angular2/src/core/annotations/annotations';
2828
import {PrivateComponentLoader} from 'angular2/src/core/compiler/private_component_loader';
2929
import {TestabilityRegistry, Testability} from 'angular2/src/core/testability/testability';
30+
import {ViewFactory, VIEW_POOL_CAPACITY} from 'angular2/src/core/compiler/view_factory';
31+
import {ProtoViewFactory} from 'angular2/src/core/compiler/proto_view_factory';
32+
import {Renderer} from 'angular2/src/render/api';
33+
import {DirectDomRenderer} from 'angular2/src/render/dom/direct_dom_renderer';
34+
import * as rc from 'angular2/src/render/dom/compiler/compiler';
35+
import * as rvf from 'angular2/src/render/dom/view/view_factory';
36+
3037
import {
3138
appViewToken,
3239
appChangeDetectorToken,
@@ -60,7 +67,7 @@ function _injectorBindings(appComponentType): List<Binding> {
6067
return element;
6168
}, [appComponentAnnotatedTypeToken, appDocumentToken]),
6269
bind(appViewToken).toAsyncFactory((changeDetection, compiler, injector, appElement,
63-
appComponentAnnotatedType, strategy, eventManager, testability, registry) => {
70+
appComponentAnnotatedType, testability, registry, viewFactory) => {
6471

6572
// We need to do this here to ensure that we create Testability and
6673
// it's ready on the window for users.
@@ -73,18 +80,18 @@ function _injectorBindings(appComponentType): List<Binding> {
7380
}
7481
return compiler.compileRoot(
7582
appElement,
76-
DirectiveBinding.createFromType(appComponentAnnotatedType.type, appComponentAnnotatedType.annotation)
83+
appComponentAnnotatedType.type
7784
).then(
7885
(appProtoView) => {
7986
// The light Dom of the app element is not considered part of
8087
// the angular application. Thus the context and lightDomInjector are
8188
// empty.
82-
var view = appProtoView.instantiate(null, eventManager);
83-
view.hydrate(injector, null, null, new Object(), null);
89+
var view = viewFactory.getView(appProtoView);
90+
view.hydrate(injector, null, new Object(), null);
8491
return view;
8592
});
8693
}, [ChangeDetection, Compiler, Injector, appElementToken, appComponentAnnotatedTypeToken,
87-
ShadowDomStrategy, EventManager, Testability, TestabilityRegistry]),
94+
Testability, TestabilityRegistry, ViewFactory]),
8895

8996
bind(appChangeDetectorToken).toFactory((rootView) => rootView.changeDetector,
9097
[appViewToken]),
@@ -98,6 +105,23 @@ function _injectorBindings(appComponentType): List<Binding> {
98105
bind(ShadowDomStrategy).toFactory(
99106
(styleUrlResolver, doc) => new EmulatedUnscopedShadowDomStrategy(styleUrlResolver, doc.head),
100107
[StyleUrlResolver, appDocumentToken]),
108+
bind(Renderer).toClass(DirectDomRenderer),
109+
bind(rc.Compiler).toClass(rc.DefaultCompiler),
110+
// TODO(tbosch): We need an explicit factory here, as
111+
// we are getting errors in dart2js with mirrors...
112+
bind(rvf.ViewFactory).toFactory(
113+
(capacity, eventManager, shadowDomStrategy) => new rvf.ViewFactory(capacity, eventManager, shadowDomStrategy),
114+
[rvf.VIEW_POOL_CAPACITY, EventManager, ShadowDomStrategy]
115+
),
116+
bind(rvf.VIEW_POOL_CAPACITY).toValue(100000),
117+
ProtoViewFactory,
118+
// TODO(tbosch): We need an explicit factory here, as
119+
// we are getting errors in dart2js with mirrors...
120+
bind(ViewFactory).toFactory(
121+
(capacity) => new ViewFactory(capacity),
122+
[VIEW_POOL_CAPACITY]
123+
),
124+
bind(VIEW_POOL_CAPACITY).toValue(100000),
101125
Compiler,
102126
CompilerCache,
103127
TemplateResolver,

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

+8-55
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,16 @@ import {Type, isBlank, isPresent, BaseException, normalizeBlank, stringify} from
33
import {Promise, PromiseWrapper} from 'angular2/src/facade/async';
44
import {List, ListWrapper, Map, MapWrapper} from 'angular2/src/facade/collection';
55

6-
import {ChangeDetection, Parser} from 'angular2/change_detection';
7-
86
import {DirectiveMetadataReader} from './directive_metadata_reader';
97
import {Component, Viewport, DynamicComponent, Decorator} from '../annotations/annotations';
108
import {ProtoView} from './view';
119
import {DirectiveBinding} from './element_injector';
1210
import {TemplateResolver} from './template_resolver';
1311
import {Template} from '../annotations/template';
14-
import {ShadowDomStrategy} from './shadow_dom_strategy';
1512
import {ComponentUrlMapper} from './component_url_mapper';
1613
import {ProtoViewFactory} from './proto_view_factory';
1714
import {UrlResolver} from 'angular2/src/services/url_resolver';
1815

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';
2416
import * as renderApi from 'angular2/src/render/api';
2517

2618
/**
@@ -49,9 +41,7 @@ export class CompilerCache {
4941
}
5042

5143

52-
// TODO(tbosch): rename this class to Compiler
53-
// and remove the current Compiler when core uses the render views.
54-
export class NewCompiler {
44+
export class Compiler {
5545
_reader: DirectiveMetadataReader;
5646
_compilerCache:CompilerCache;
5747
_compiling:Map<Type, Promise>;
@@ -80,19 +70,19 @@ export class NewCompiler {
8070
this._protoViewFactory = protoViewFactory;
8171
}
8272

83-
_bindDirective(directive) {
84-
var meta = this._reader.read(directive);
73+
_bindDirective(directiveTypeOrBinding) {
74+
if (directiveTypeOrBinding instanceof DirectiveBinding) {
75+
return directiveTypeOrBinding;
76+
}
77+
var meta = this._reader.read(directiveTypeOrBinding);
8578
return DirectiveBinding.createFromType(meta.type, meta.annotation);
8679
}
8780

8881
// Create a rootView as if the compiler encountered <rootcmp></rootcmp>.
8982
// Used for bootstrapping.
90-
compileRoot(elementOrSelector, componentBinding:DirectiveBinding):Promise<ProtoView> {
83+
compileRoot(elementOrSelector, componentTypeOrBinding:any):Promise<ProtoView> {
9184
return this._renderer.createRootProtoView(elementOrSelector, 'root').then( (rootRenderPv) => {
92-
return this._compileNestedProtoViews(null, rootRenderPv, [componentBinding], true)
93-
}).then( (rootProtoView) => {
94-
rootProtoView.instantiateInPlace = true;
95-
return rootProtoView;
85+
return this._compileNestedProtoViews(null, rootRenderPv, [this._bindDirective(componentTypeOrBinding)], true);
9686
});
9787
}
9888

@@ -266,40 +256,3 @@ export class NewCompiler {
266256
}
267257

268258
}
269-
270-
// TODO(tbosch): delete this class once we use the render views
271-
/**
272-
* The compiler loads and translates the html templates of components into
273-
* nested ProtoViews. To decompose its functionality it uses
274-
* the render compiler.
275-
*
276-
* @publicModule angular2/template
277-
*/
278-
@Injectable()
279-
export class Compiler extends NewCompiler {
280-
constructor(changeDetection:ChangeDetection,
281-
templateLoader:TemplateLoader,
282-
reader: DirectiveMetadataReader,
283-
parser:Parser,
284-
cache:CompilerCache,
285-
shadowDomStrategy: ShadowDomStrategy,
286-
templateResolver: TemplateResolver,
287-
componentUrlMapper: ComponentUrlMapper,
288-
urlResolver: UrlResolver) {
289-
super(
290-
reader,
291-
cache,
292-
templateResolver,
293-
componentUrlMapper,
294-
urlResolver,
295-
new DirectDomRenderer(
296-
new rc.Compiler(
297-
new DefaultStepFactory(parser, shadowDomStrategy.render),
298-
templateLoader
299-
),
300-
null, shadowDomStrategy.render
301-
),
302-
new ProtoViewFactory(changeDetection, shadowDomStrategy)
303-
);
304-
}
305-
}

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

-9
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,8 @@ export class ElementBinder {
88
protoElementInjector:eiModule.ProtoElementInjector;
99
componentDirective:DirectiveBinding;
1010
viewportDirective:DirectiveBinding;
11-
textNodeIndices:List<int>;
12-
hasElementPropertyBindings:boolean;
1311
nestedProtoView: viewModule.ProtoView;
1412
events:StringMap;
15-
contentTagSelector:string;
1613
parent:ElementBinder;
1714
index:int;
1815
distanceToParent:int;
@@ -32,13 +29,7 @@ export class ElementBinder {
3229
this.distanceToParent = distanceToParent;
3330
// updated later when events are bound
3431
this.events = null;
35-
// updated later when text nodes are bound
36-
this.textNodeIndices = null;
37-
// updated later when element properties are bound
38-
this.hasElementPropertyBindings = false;
3932
// updated later, so we are able to resolve cycles
4033
this.nestedProtoView = null;
41-
// updated later in the compilation pipeline
42-
this.contentTagSelector = null;
4334
}
4435
}

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

+19-26
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,10 @@ import {Parent, Ancestor} from 'angular2/src/core/annotations/visibility';
66
import {EventEmitter, PropertySetter, Attribute} from 'angular2/src/core/annotations/di';
77
import * as viewModule from 'angular2/src/core/compiler/view';
88
import {ViewContainer} from 'angular2/src/core/compiler/view_container';
9-
import {NgElement} from 'angular2/src/core/dom/element';
9+
import {NgElement} from 'angular2/src/core/compiler/ng_element';
1010
import {Directive, onChange, onDestroy, onAllChangesDone} from 'angular2/src/core/annotations/annotations';
1111
import {BindingPropagationConfig} from 'angular2/change_detection';
1212
import * as pclModule from 'angular2/src/core/compiler/private_component_location';
13-
import {setterFactory} from 'angular2/src/render/dom/view/property_setter_factory';
1413

1514
var _MAX_DIRECTIVE_CONSTRUCTION_COUNTER = 10;
1615

@@ -268,8 +267,8 @@ export class ProtoElementInjector {
268267
}
269268
}
270269

271-
instantiate(parent:ElementInjector, host:ElementInjector):ElementInjector {
272-
return new ElementInjector(this, parent, host);
270+
instantiate(parent:ElementInjector):ElementInjector {
271+
return new ElementInjector(this, parent);
273272
}
274273

275274
directParent(): ProtoElementInjector {
@@ -339,21 +338,12 @@ export class ElementInjector extends TreeNode {
339338
_privateComponent;
340339
_privateComponentBinding:DirectiveBinding;
341340

342-
constructor(proto:ProtoElementInjector, parent:ElementInjector, host:ElementInjector) {
341+
constructor(proto:ProtoElementInjector, parent:ElementInjector) {
343342
super(parent);
344-
if (isPresent(parent) && isPresent(host)) {
345-
throw new BaseException('Only either parent or host is allowed');
346-
}
347-
this._host = null; // needed to satisfy Dart
348-
if (isPresent(parent)) {
349-
this._host = parent._host;
350-
} else {
351-
this._host = host;
352-
}
353-
354343
this._proto = proto;
355344

356345
//we cannot call clearDirectives because fields won't be detected
346+
this._host = null;
357347
this._preBuiltObjects = null;
358348
this._lightDomAppInjector = null;
359349
this._shadowDomAppInjector = null;
@@ -371,6 +361,7 @@ export class ElementInjector extends TreeNode {
371361
}
372362

373363
clearDirectives() {
364+
this._host = null;
374365
this._preBuiltObjects = null;
375366
this._lightDomAppInjector = null;
376367
this._shadowDomAppInjector = null;
@@ -406,7 +397,8 @@ export class ElementInjector extends TreeNode {
406397
this._constructionCounter = 0;
407398
}
408399

409-
instantiateDirectives(lightDomAppInjector:Injector, shadowDomAppInjector:Injector, preBuiltObjects:PreBuiltObjects) {
400+
instantiateDirectives(lightDomAppInjector:Injector, host:ElementInjector, shadowDomAppInjector:Injector, preBuiltObjects:PreBuiltObjects) {
401+
this._host = host;
410402
this._checkShadowDomAppInjector(shadowDomAppInjector);
411403

412404
this._preBuiltObjects = preBuiltObjects;
@@ -456,10 +448,6 @@ export class ElementInjector extends TreeNode {
456448
return pb !== _undefined && isPresent(pb);
457449
}
458450

459-
forElement(el):boolean {
460-
return this._preBuiltObjects.element.domElement === el;
461-
}
462-
463451
/** Gets the NgElement associated with this ElementInjector */
464452
getNgElement() {
465453
return this._preBuiltObjects.element;
@@ -538,6 +526,10 @@ export class ElementInjector extends TreeNode {
538526
return obj;
539527
}
540528

529+
getBoundElementIndex() {
530+
return this._proto.index;
531+
}
532+
541533
_getByDependency(dep:DirectiveDependency, requestor:Key) {
542534
if (isPresent(dep.eventEmitterName)) return this._buildEventEmitter(dep);
543535
if (isPresent(dep.propSetterName)) return this._buildPropSetter(dep);
@@ -553,10 +545,12 @@ export class ElementInjector extends TreeNode {
553545
}
554546

555547
_buildPropSetter(dep) {
556-
var ngElement = this._getPreBuiltObjectByKeyId(StaticKeys.instance().ngElementId);
557-
var domElement = ngElement.domElement;
558-
var setter = setterFactory(dep.propSetterName);
559-
return function(v) { setter(domElement, v) };
548+
var view = this._getPreBuiltObjectByKeyId(StaticKeys.instance().viewId);
549+
var renderer = view.proto.renderer;
550+
var index = this._proto.index;
551+
return function(v) {
552+
renderer.setElementProperty(view.render, index, dep.propSetterName, v);
553+
};
560554
}
561555

562556
_buildAttribute(dep): string {
@@ -582,7 +576,6 @@ export class ElementInjector extends TreeNode {
582576
*/
583577
_getByKey(key:Key, depth:number, optional:boolean, requestor:Key) {
584578
var ei = this;
585-
586579
if (! this._shouldIncludeSelf(depth)) {
587580
depth -= ei._proto.distanceToParent;
588581
ei = ei._parent;
@@ -631,7 +624,7 @@ export class ElementInjector extends TreeNode {
631624
if (keyId === staticKeys.bindingPropagationConfigId) return this._preBuiltObjects.bindingPropagationConfig;
632625

633626
if (keyId === staticKeys.privateComponentLocationId) {
634-
return new pclModule.PrivateComponentLocation(this, this._preBuiltObjects.element, this._preBuiltObjects.view);
627+
return new pclModule.PrivateComponentLocation(this, this._preBuiltObjects.view);
635628
}
636629

637630
//TODO add other objects as needed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import {DOM} from 'angular2/src/dom/dom_adapter';
2+
import {normalizeBlank} from 'angular2/src/facade/lang';
3+
import * as viewModule from '../compiler/view';
4+
import {DirectDomViewRef} from 'angular2/src/render/dom/direct_dom_renderer';
5+
6+
/**
7+
* Allows direct access to the underlying DOM element.
8+
*
9+
* Attention: NgElement will be replaced by a different concept
10+
* for accessing an element in a way that is compatible with the render layer.
11+
*
12+
* @publicModule angular2/angular2
13+
*/
14+
export class NgElement {
15+
_view:viewModule.View;
16+
_boundElementIndex:number;
17+
18+
constructor(view, boundElementIndex) {
19+
this._view = view;
20+
this._boundElementIndex = boundElementIndex;
21+
}
22+
23+
// TODO(tbosch): Here we expose the real DOM element.
24+
// We need a more general way to read/write to the DOM element
25+
// via a proper abstraction in the render layer
26+
get domElement() {
27+
var domViewRef:DirectDomViewRef = this._view.render;
28+
return domViewRef.delegate.boundElements[this._boundElementIndex];
29+
}
30+
31+
getAttribute(name:string) {
32+
return normalizeBlank(DOM.getAttribute(this.domElement, name));
33+
}
34+
}

0 commit comments

Comments
 (0)