refactor(render): create and store render ProtoViewRef in every app ProtoView

Needed to change Renderer.mergeChildComponentProtoViews to not create
new ProtoViews to be able to deal with cyclic references.

This commit is part of using the new render layer in Angular.
This commit is contained in:
Tobias Bosch
2015-04-07 17:24:09 -07:00
parent d6003ee0ab
commit ca958464c4
16 changed files with 509 additions and 436 deletions

View File

@ -141,20 +141,20 @@ export class Renderer {
compile(template:Template):Promise<ProtoView> { return null; }
/**
* Creates a new ProtoView with preset nested components,
* Sets the preset nested components,
* which will be instantiated when this protoView is instantiated.
* Note: We can't create new ProtoViewRefs here as we need to support cycles / recursive components.
* @param {List<ProtoViewRef>} protoViewRefs
* ProtoView for every element with a component in this protoView or in a view container's protoView
* @return {List<ProtoViewRef>}
* new ProtoViewRef for the given protoView and all of its view container's protoViews
*/
mergeChildComponentProtoViews(protoViewRef:ProtoViewRef, protoViewRefs:List<ProtoViewRef>):List<ProtoViewRef> { return null; }
mergeChildComponentProtoViews(protoViewRef:ProtoViewRef, componentProtoViewRefs:List<ProtoViewRef>) { return null; }
/**
* Creats a ProtoView that will create a root view for the given element,
* i.e. it will not clone the element but only attach other proto views to it.
* Contains a single nested component with the given componentId.
*/
createRootProtoView(selectorOrElement):ProtoViewRef { return null; }
createRootProtoView(selectorOrElement, componentId):Promise<ProtoView> { return null; }
/**
* Creates a view and all of its nested child components.

View File

@ -1,4 +1,4 @@
import {Promise} from 'angular2/src/facade/async';
import {Promise, PromiseWrapper} from 'angular2/src/facade/async';
import {List, ListWrapper} from 'angular2/src/facade/collection';
import {isBlank, isPresent} from 'angular2/src/facade/lang';
@ -26,10 +26,6 @@ function _wrapView(view:View) {
return new _DirectDomViewRef(view);
}
function _wrapProtoView(protoView:ProtoView) {
return new DirectDomProtoViewRef(protoView);
}
function _collectComponentChildViewRefs(view, target = null) {
if (isBlank(target)) {
target = [];
@ -83,22 +79,22 @@ export class DirectDomRenderer extends api.Renderer {
return this._compiler.compile(template);
}
mergeChildComponentProtoViews(protoViewRef:api.ProtoViewRef, protoViewRefs:List<api.ProtoViewRef>):List<api.ProtoViewRef> {
var protoViews = [];
mergeChildComponentProtoViews(protoViewRef:api.ProtoViewRef, protoViewRefs:List<api.ProtoViewRef>) {
_resolveProtoView(protoViewRef).mergeChildComponentProtoViews(
ListWrapper.map(protoViewRefs, _resolveProtoView),
protoViews
ListWrapper.map(protoViewRefs, _resolveProtoView)
);
return ListWrapper.map(protoViews, _wrapProtoView);
}
createRootProtoView(selectorOrElement):api.ProtoViewRef {
createRootProtoView(selectorOrElement, componentId):Promise<api.ProtoView> {
var element = selectorOrElement; // TODO: select the element if it is not a real element...
var rootProtoViewBuilder = new ProtoViewBuilder(element);
rootProtoViewBuilder.setIsRootView(true);
rootProtoViewBuilder.bindElement(element, 'root element').setComponentId('root');
this._shadowDomStrategy.processElement(null, 'root', element);
return rootProtoViewBuilder.build().render;
var elBinder = rootProtoViewBuilder.bindElement(element, 'root element');
elBinder.setComponentId(componentId);
elBinder.bindDirective(0);
this._shadowDomStrategy.processElement(null, componentId, element);
return PromiseWrapper.resolve(rootProtoViewBuilder.build());
}
createView(protoViewRef:api.ProtoViewRef):List<api.ViewRef> {

View File

@ -1,12 +1,8 @@
import {AST} from 'angular2/change_detection';
import {SetterFn} from 'angular2/src/reflection/types';
import {isPresent, isBlank, BaseException} from 'angular2/src/facade/lang';
import {List, ListWrapper} from 'angular2/src/facade/collection';
import * as protoViewModule from './proto_view';
/**
* Note: Code that uses this class assumes that is immutable!
*/
export class ElementBinder {
contentTagSelector: string;
textNodeIndices: List<number>;
@ -39,24 +35,4 @@ export class ElementBinder {
this.distanceToParent = distanceToParent;
this.propertySetters = propertySetters;
}
mergeChildComponentProtoViews(protoViews:List<protoViewModule.ProtoView>, target:List<protoViewModule.ProtoView>):ElementBinder {
var nestedProtoView;
if (isPresent(this.componentId)) {
nestedProtoView = ListWrapper.removeAt(protoViews, 0);
} else if (isPresent(this.nestedProtoView)) {
nestedProtoView = this.nestedProtoView.mergeChildComponentProtoViews(protoViews, target);
}
return new ElementBinder({
parentIndex: this.parentIndex,
textNodeIndices: this.textNodeIndices,
contentTagSelector: this.contentTagSelector,
nestedProtoView: nestedProtoView,
componentId: this.componentId,
eventLocals: this.eventLocals,
eventNames: this.eventNames,
distanceToParent: this.distanceToParent,
propertySetters: this.propertySetters
});
}
}

View File

@ -6,9 +6,6 @@ import {List, Map, ListWrapper, MapWrapper} from 'angular2/src/facade/collection
import {ElementBinder} from './element_binder';
import {NG_BINDING_CLASS} from '../util';
/**
* Note: Code that uses this class assumes that is immutable!
*/
export class ProtoView {
element;
elementBinders:List<ElementBinder>;
@ -28,22 +25,14 @@ export class ProtoView {
this.rootBindingOffset = (isPresent(this.element) && DOM.hasClass(this.element, NG_BINDING_CLASS)) ? 1 : 0;
}
mergeChildComponentProtoViews(protoViews:List<ProtoView>, target:List<ProtoView>):ProtoView {
var elementBinders = ListWrapper.createFixedSize(this.elementBinders.length);
mergeChildComponentProtoViews(componentProtoViews:List<ProtoView>) {
var componentProtoViewIndex = 0;
for (var i=0; i<this.elementBinders.length; i++) {
var eb = this.elementBinders[i];
if (isPresent(eb.componentId) || isPresent(eb.nestedProtoView)) {
elementBinders[i] = eb.mergeChildComponentProtoViews(protoViews, target);
} else {
elementBinders[i] = eb;
if (isPresent(eb.componentId)) {
eb.nestedProtoView = componentProtoViews[componentProtoViewIndex];
componentProtoViewIndex++;
}
}
var result = new ProtoView({
elementBinders: elementBinders,
element: this.element,
isRootView: this.isRootView
});
ListWrapper.insert(target, 0, result);
return result
}
}