refactor(proto_view_factory): Move getChangeDetectorDefinitions out of ProtoViewFactory
Move `getChangeDetectorDefinitions` out of `ProtoViewFactory` since it does not depend on any state in that object.
This commit is contained in:
parent
c397297eef
commit
3644036693
|
@ -110,37 +110,19 @@ class BindingRecordsCreator {
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ProtoViewFactory {
|
export class ProtoViewFactory {
|
||||||
_changeDetection:ChangeDetection;
|
_changeDetection: ChangeDetection;
|
||||||
|
|
||||||
constructor(changeDetection:ChangeDetection) {
|
constructor(changeDetection: ChangeDetection) {
|
||||||
this._changeDetection = changeDetection;
|
this._changeDetection = changeDetection;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the data needed to create ChangeDetectors
|
|
||||||
* for the given ProtoView and all nested ProtoViews.
|
|
||||||
*/
|
|
||||||
getChangeDetectorDefinitions(hostComponentMetadata:renderApi.DirectiveMetadata,
|
|
||||||
rootRenderProtoView: renderApi.ProtoViewDto, allRenderDirectiveMetadata:List<renderApi.DirectiveMetadata>):List<ChangeDetectorDefinition> {
|
|
||||||
var nestedPvsWithIndex = this._collectNestedProtoViews(rootRenderProtoView);
|
|
||||||
var nestedPvVariableBindings = this._collectNestedProtoViewsVariableBindings(nestedPvsWithIndex);
|
|
||||||
var nestedPvVariableNames = this._collectNestedProtoViewsVariableNames(nestedPvsWithIndex, nestedPvVariableBindings);
|
|
||||||
|
|
||||||
return this._getChangeDetectorDefinitions(
|
|
||||||
hostComponentMetadata,
|
|
||||||
nestedPvsWithIndex,
|
|
||||||
nestedPvVariableNames,
|
|
||||||
allRenderDirectiveMetadata
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
createAppProtoViews(hostComponentBinding:DirectiveBinding,
|
createAppProtoViews(hostComponentBinding:DirectiveBinding,
|
||||||
rootRenderProtoView: renderApi.ProtoViewDto, allDirectives:List<DirectiveBinding>):List<AppProtoView> {
|
rootRenderProtoView: renderApi.ProtoViewDto, allDirectives:List<DirectiveBinding>):List<AppProtoView> {
|
||||||
var allRenderDirectiveMetadata = ListWrapper.map(allDirectives, directiveBinding => directiveBinding.metadata );
|
var allRenderDirectiveMetadata = ListWrapper.map(allDirectives, directiveBinding => directiveBinding.metadata);
|
||||||
var nestedPvsWithIndex = this._collectNestedProtoViews(rootRenderProtoView);
|
var nestedPvsWithIndex = _collectNestedProtoViews(rootRenderProtoView);
|
||||||
var nestedPvVariableBindings = this._collectNestedProtoViewsVariableBindings(nestedPvsWithIndex);
|
var nestedPvVariableBindings = _collectNestedProtoViewsVariableBindings(nestedPvsWithIndex);
|
||||||
var nestedPvVariableNames = this._collectNestedProtoViewsVariableNames(nestedPvsWithIndex, nestedPvVariableBindings);
|
var nestedPvVariableNames = _collectNestedProtoViewsVariableNames(nestedPvsWithIndex, nestedPvVariableBindings);
|
||||||
var changeDetectorDefs = this._getChangeDetectorDefinitions(
|
var changeDetectorDefs = _getChangeDetectorDefinitions(
|
||||||
hostComponentBinding.metadata, nestedPvsWithIndex, nestedPvVariableNames, allRenderDirectiveMetadata
|
hostComponentBinding.metadata, nestedPvsWithIndex, nestedPvVariableNames, allRenderDirectiveMetadata
|
||||||
);
|
);
|
||||||
var protoChangeDetectors = ListWrapper.map(
|
var protoChangeDetectors = ListWrapper.map(
|
||||||
|
@ -148,7 +130,7 @@ export class ProtoViewFactory {
|
||||||
);
|
);
|
||||||
var appProtoViews = ListWrapper.createFixedSize(nestedPvsWithIndex.length);
|
var appProtoViews = ListWrapper.createFixedSize(nestedPvsWithIndex.length);
|
||||||
ListWrapper.forEach(nestedPvsWithIndex, (pvWithIndex) => {
|
ListWrapper.forEach(nestedPvsWithIndex, (pvWithIndex) => {
|
||||||
var appProtoView = this._createAppProtoView(
|
var appProtoView = _createAppProtoView(
|
||||||
pvWithIndex.renderProtoView,
|
pvWithIndex.renderProtoView,
|
||||||
protoChangeDetectors[pvWithIndex.index],
|
protoChangeDetectors[pvWithIndex.index],
|
||||||
nestedPvVariableBindings[pvWithIndex.index],
|
nestedPvVariableBindings[pvWithIndex.index],
|
||||||
|
@ -162,208 +144,232 @@ export class ProtoViewFactory {
|
||||||
});
|
});
|
||||||
return appProtoViews;
|
return appProtoViews;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_collectNestedProtoViews(renderProtoView:renderApi.ProtoViewDto, parentIndex:number = null, boundElementIndex = null, result:List<RenderProtoViewWithIndex> = null):List<RenderProtoViewWithIndex> {
|
/**
|
||||||
if (isBlank(result)) {
|
* Returns the data needed to create ChangeDetectors
|
||||||
result = [];
|
* for the given ProtoView and all nested ProtoViews.
|
||||||
|
*/
|
||||||
|
export function getChangeDetectorDefinitions(
|
||||||
|
hostComponentMetadata:renderApi.DirectiveMetadata,
|
||||||
|
rootRenderProtoView: renderApi.ProtoViewDto,
|
||||||
|
allRenderDirectiveMetadata:List<renderApi.DirectiveMetadata>): List<ChangeDetectorDefinition> {
|
||||||
|
var nestedPvsWithIndex = _collectNestedProtoViews(rootRenderProtoView);
|
||||||
|
var nestedPvVariableBindings = _collectNestedProtoViewsVariableBindings(nestedPvsWithIndex);
|
||||||
|
var nestedPvVariableNames = _collectNestedProtoViewsVariableNames(nestedPvsWithIndex, nestedPvVariableBindings);
|
||||||
|
|
||||||
|
return _getChangeDetectorDefinitions(
|
||||||
|
hostComponentMetadata,
|
||||||
|
nestedPvsWithIndex,
|
||||||
|
nestedPvVariableNames,
|
||||||
|
allRenderDirectiveMetadata
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _collectNestedProtoViews(renderProtoView:renderApi.ProtoViewDto,
|
||||||
|
parentIndex:number = null,
|
||||||
|
boundElementIndex = null,
|
||||||
|
result:List<RenderProtoViewWithIndex> = null): List<RenderProtoViewWithIndex> {
|
||||||
|
if (isBlank(result)) {
|
||||||
|
result = [];
|
||||||
|
}
|
||||||
|
ListWrapper.push(result, new RenderProtoViewWithIndex(renderProtoView, result.length, parentIndex, boundElementIndex));
|
||||||
|
var currentIndex = result.length - 1;
|
||||||
|
var childBoundElementIndex = 0;
|
||||||
|
ListWrapper.forEach(renderProtoView.elementBinders, (elementBinder) => {
|
||||||
|
if (isPresent(elementBinder.nestedProtoView)) {
|
||||||
|
_collectNestedProtoViews(elementBinder.nestedProtoView, currentIndex, childBoundElementIndex, result);
|
||||||
}
|
}
|
||||||
ListWrapper.push(result, new RenderProtoViewWithIndex(renderProtoView, result.length, parentIndex, boundElementIndex));
|
childBoundElementIndex++;
|
||||||
var currentIndex = result.length - 1;
|
});
|
||||||
var childBoundElementIndex = 0;
|
return result;
|
||||||
ListWrapper.forEach(renderProtoView.elementBinders, (elementBinder) => {
|
}
|
||||||
if (isPresent(elementBinder.nestedProtoView)) {
|
|
||||||
this._collectNestedProtoViews(elementBinder.nestedProtoView, currentIndex, childBoundElementIndex, result);
|
|
||||||
}
|
|
||||||
childBoundElementIndex++;
|
|
||||||
});
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
_getChangeDetectorDefinitions(
|
function _getChangeDetectorDefinitions(
|
||||||
hostComponentMetadata:renderApi.DirectiveMetadata,
|
hostComponentMetadata:renderApi.DirectiveMetadata,
|
||||||
nestedPvsWithIndex: List<RenderProtoViewWithIndex>,
|
nestedPvsWithIndex: List<RenderProtoViewWithIndex>,
|
||||||
nestedPvVariableNames: List<List<string>>,
|
nestedPvVariableNames: List<List<string>>,
|
||||||
allRenderDirectiveMetadata:List<renderApi.DirectiveMetadata>):List<ChangeDetectorDefinition> {
|
allRenderDirectiveMetadata:List<renderApi.DirectiveMetadata>):List<ChangeDetectorDefinition> {
|
||||||
return ListWrapper.map(nestedPvsWithIndex, (pvWithIndex) => {
|
return ListWrapper.map(nestedPvsWithIndex, (pvWithIndex) => {
|
||||||
var elementBinders = pvWithIndex.renderProtoView.elementBinders;
|
var elementBinders = pvWithIndex.renderProtoView.elementBinders;
|
||||||
var bindingRecordsCreator = new BindingRecordsCreator();
|
var bindingRecordsCreator = new BindingRecordsCreator();
|
||||||
var bindingRecords = bindingRecordsCreator.getBindingRecords(elementBinders, allRenderDirectiveMetadata);
|
var bindingRecords = bindingRecordsCreator.getBindingRecords(elementBinders, allRenderDirectiveMetadata);
|
||||||
var directiveRecords = bindingRecordsCreator.getDirectiveRecords(elementBinders, allRenderDirectiveMetadata);
|
var directiveRecords = bindingRecordsCreator.getDirectiveRecords(elementBinders, allRenderDirectiveMetadata);
|
||||||
var strategyName = DEFAULT;
|
var strategyName = DEFAULT;
|
||||||
var typeString;
|
var typeString;
|
||||||
if (pvWithIndex.renderProtoView.type === renderApi.ProtoViewDto.COMPONENT_VIEW_TYPE) {
|
if (pvWithIndex.renderProtoView.type === renderApi.ProtoViewDto.COMPONENT_VIEW_TYPE) {
|
||||||
strategyName = hostComponentMetadata.changeDetection;
|
strategyName = hostComponentMetadata.changeDetection;
|
||||||
typeString = 'comp';
|
typeString = 'comp';
|
||||||
} else if (pvWithIndex.renderProtoView.type === renderApi.ProtoViewDto.HOST_VIEW_TYPE) {
|
} else if (pvWithIndex.renderProtoView.type === renderApi.ProtoViewDto.HOST_VIEW_TYPE) {
|
||||||
typeString = 'host';
|
typeString = 'host';
|
||||||
} else {
|
} else {
|
||||||
typeString = 'embedded';
|
typeString = 'embedded';
|
||||||
}
|
}
|
||||||
var id = `${hostComponentMetadata.id}_${typeString}_${pvWithIndex.index}`;
|
var id = `${hostComponentMetadata.id}_${typeString}_${pvWithIndex.index}`;
|
||||||
var variableNames = nestedPvVariableNames[pvWithIndex.index];
|
var variableNames = nestedPvVariableNames[pvWithIndex.index];
|
||||||
return new ChangeDetectorDefinition(id, strategyName, variableNames, bindingRecords, directiveRecords);
|
return new ChangeDetectorDefinition(id, strategyName, variableNames, bindingRecords, directiveRecords);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
_createAppProtoView(
|
function _createAppProtoView(
|
||||||
renderProtoView: renderApi.ProtoViewDto,
|
renderProtoView: renderApi.ProtoViewDto,
|
||||||
protoChangeDetector: ProtoChangeDetector,
|
protoChangeDetector: ProtoChangeDetector,
|
||||||
variableBindings: Map<string, string>,
|
variableBindings: Map<string, string>,
|
||||||
allDirectives:List<DirectiveBinding>
|
allDirectives:List<DirectiveBinding>
|
||||||
):AppProtoView {
|
):AppProtoView {
|
||||||
var elementBinders = renderProtoView.elementBinders;
|
var elementBinders = renderProtoView.elementBinders;
|
||||||
var protoView = new AppProtoView(renderProtoView.render, protoChangeDetector, variableBindings);
|
var protoView = new AppProtoView(renderProtoView.render, protoChangeDetector, variableBindings);
|
||||||
|
|
||||||
// TODO: vsavkin refactor to pass element binders into proto view
|
// TODO: vsavkin refactor to pass element binders into proto view
|
||||||
this._createElementBinders(protoView, elementBinders, allDirectives);
|
_createElementBinders(protoView, elementBinders, allDirectives);
|
||||||
this._bindDirectiveEvents(protoView, elementBinders);
|
_bindDirectiveEvents(protoView, elementBinders);
|
||||||
|
|
||||||
return protoView;
|
return protoView;
|
||||||
}
|
}
|
||||||
|
|
||||||
_collectNestedProtoViewsVariableBindings(
|
function _collectNestedProtoViewsVariableBindings(
|
||||||
nestedPvsWithIndex: List<RenderProtoViewWithIndex>
|
nestedPvsWithIndex: List<RenderProtoViewWithIndex>
|
||||||
):List<Map<string, string>> {
|
):List<Map<string, string>> {
|
||||||
return ListWrapper.map(nestedPvsWithIndex, (pvWithIndex) => {
|
return ListWrapper.map(nestedPvsWithIndex, (pvWithIndex) => {
|
||||||
return this._createVariableBindings(pvWithIndex.renderProtoView);
|
return _createVariableBindings(pvWithIndex.renderProtoView);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
_createVariableBindings(renderProtoView):Map {
|
function _createVariableBindings(renderProtoView):Map {
|
||||||
var variableBindings = MapWrapper.create();
|
var variableBindings = MapWrapper.create();
|
||||||
MapWrapper.forEach(renderProtoView.variableBindings, (mappedName, varName) => {
|
MapWrapper.forEach(renderProtoView.variableBindings, (mappedName, varName) => {
|
||||||
|
MapWrapper.set(variableBindings, varName, mappedName);
|
||||||
|
});
|
||||||
|
ListWrapper.forEach(renderProtoView.elementBinders, binder => {
|
||||||
|
MapWrapper.forEach(binder.variableBindings, (mappedName, varName) => {
|
||||||
MapWrapper.set(variableBindings, varName, mappedName);
|
MapWrapper.set(variableBindings, varName, mappedName);
|
||||||
});
|
});
|
||||||
ListWrapper.forEach(renderProtoView.elementBinders, binder => {
|
});
|
||||||
MapWrapper.forEach(binder.variableBindings, (mappedName, varName) => {
|
return variableBindings;
|
||||||
MapWrapper.set(variableBindings, varName, mappedName);
|
}
|
||||||
});
|
|
||||||
});
|
|
||||||
return variableBindings;
|
|
||||||
}
|
|
||||||
|
|
||||||
_collectNestedProtoViewsVariableNames(
|
function _collectNestedProtoViewsVariableNames(
|
||||||
nestedPvsWithIndex: List<RenderProtoViewWithIndex>,
|
nestedPvsWithIndex: List<RenderProtoViewWithIndex>,
|
||||||
nestedPvVariableBindings:List<Map<string, string>>
|
nestedPvVariableBindings:List<Map<string, string>>
|
||||||
):List<List<string>> {
|
):List<List<string>> {
|
||||||
var nestedPvVariableNames = ListWrapper.createFixedSize(nestedPvsWithIndex.length);
|
var nestedPvVariableNames = ListWrapper.createFixedSize(nestedPvsWithIndex.length);
|
||||||
ListWrapper.forEach(nestedPvsWithIndex, (pvWithIndex) => {
|
ListWrapper.forEach(nestedPvsWithIndex, (pvWithIndex) => {
|
||||||
var parentVariableNames = isPresent(pvWithIndex.parentIndex) ? nestedPvVariableNames[pvWithIndex.parentIndex] : null;
|
var parentVariableNames = isPresent(pvWithIndex.parentIndex) ? nestedPvVariableNames[pvWithIndex.parentIndex] : null;
|
||||||
nestedPvVariableNames[pvWithIndex.index] = this._createVariableNames(
|
nestedPvVariableNames[pvWithIndex.index] = _createVariableNames(
|
||||||
parentVariableNames, nestedPvVariableBindings[pvWithIndex.index]
|
parentVariableNames, nestedPvVariableBindings[pvWithIndex.index]
|
||||||
);
|
|
||||||
});
|
|
||||||
return nestedPvVariableNames;
|
|
||||||
}
|
|
||||||
|
|
||||||
_createVariableNames(parentVariableNames, variableBindings):List {
|
|
||||||
var variableNames = isPresent(parentVariableNames) ? ListWrapper.clone(parentVariableNames) : [];
|
|
||||||
MapWrapper.forEach(variableBindings, (local, v) => {
|
|
||||||
ListWrapper.push(variableNames, local);
|
|
||||||
});
|
|
||||||
return variableNames;
|
|
||||||
}
|
|
||||||
|
|
||||||
_createElementBinders(protoView, elementBinders, allDirectiveBindings) {
|
|
||||||
for (var i=0; i<elementBinders.length; i++) {
|
|
||||||
var renderElementBinder = elementBinders[i];
|
|
||||||
var dirs = elementBinders[i].directives;
|
|
||||||
|
|
||||||
var parentPeiWithDistance = this._findParentProtoElementInjectorWithDistance(
|
|
||||||
i, protoView.elementBinders, elementBinders);
|
|
||||||
var directiveBindings = ListWrapper.map(dirs, (dir) => allDirectiveBindings[dir.directiveIndex] );
|
|
||||||
var componentDirectiveBinding = null;
|
|
||||||
if (directiveBindings.length > 0) {
|
|
||||||
if (directiveBindings[0].metadata.type === renderApi.DirectiveMetadata.COMPONENT_TYPE) {
|
|
||||||
componentDirectiveBinding = directiveBindings[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var protoElementInjector = this._createProtoElementInjector(
|
|
||||||
i, parentPeiWithDistance, renderElementBinder, componentDirectiveBinding, directiveBindings);
|
|
||||||
|
|
||||||
this._createElementBinder(protoView, i, renderElementBinder, protoElementInjector, componentDirectiveBinding);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_findParentProtoElementInjectorWithDistance(binderIndex, elementBinders, renderElementBinders) {
|
|
||||||
var distance = 0;
|
|
||||||
do {
|
|
||||||
var renderElementBinder = renderElementBinders[binderIndex];
|
|
||||||
binderIndex = renderElementBinder.parentIndex;
|
|
||||||
if (binderIndex !== -1) {
|
|
||||||
distance += renderElementBinder.distanceToParent;
|
|
||||||
var elementBinder = elementBinders[binderIndex];
|
|
||||||
if (isPresent(elementBinder.protoElementInjector)) {
|
|
||||||
return new ParentProtoElementInjectorWithDistance(elementBinder.protoElementInjector, distance);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} while (binderIndex !== -1);
|
|
||||||
return new ParentProtoElementInjectorWithDistance(null, -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
_createProtoElementInjector(binderIndex, parentPeiWithDistance, renderElementBinder, componentDirectiveBinding, directiveBindings) {
|
|
||||||
var protoElementInjector = null;
|
|
||||||
// Create a protoElementInjector for any element that either has bindings *or* has one
|
|
||||||
// or more var- defined. Elements with a var- defined need a their own element injector
|
|
||||||
// so that, when hydrating, $implicit can be set to the element.
|
|
||||||
var hasVariables = MapWrapper.size(renderElementBinder.variableBindings) > 0;
|
|
||||||
if (directiveBindings.length > 0 || hasVariables) {
|
|
||||||
protoElementInjector = new ProtoElementInjector(
|
|
||||||
parentPeiWithDistance.protoElementInjector, binderIndex,
|
|
||||||
directiveBindings,
|
|
||||||
isPresent(componentDirectiveBinding), parentPeiWithDistance.distance
|
|
||||||
);
|
|
||||||
protoElementInjector.attributes = renderElementBinder.readAttributes;
|
|
||||||
if (hasVariables) {
|
|
||||||
protoElementInjector.exportComponent = isPresent(componentDirectiveBinding);
|
|
||||||
protoElementInjector.exportElement = isBlank(componentDirectiveBinding);
|
|
||||||
|
|
||||||
// experiment
|
|
||||||
var exportImplicitName = MapWrapper.get(renderElementBinder.variableBindings, '\$implicit');
|
|
||||||
if (isPresent(exportImplicitName)) {
|
|
||||||
protoElementInjector.exportImplicitName = exportImplicitName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return protoElementInjector;
|
|
||||||
}
|
|
||||||
|
|
||||||
_createElementBinder(protoView, boundElementIndex, renderElementBinder, protoElementInjector, componentDirectiveBinding) {
|
|
||||||
var parent = null;
|
|
||||||
if (renderElementBinder.parentIndex !== -1) {
|
|
||||||
parent = protoView.elementBinders[renderElementBinder.parentIndex];
|
|
||||||
}
|
|
||||||
var elBinder = protoView.bindElement(
|
|
||||||
parent,
|
|
||||||
renderElementBinder.distanceToParent,
|
|
||||||
protoElementInjector,
|
|
||||||
componentDirectiveBinding
|
|
||||||
);
|
);
|
||||||
protoView.bindEvent(renderElementBinder.eventBindings, boundElementIndex, -1);
|
});
|
||||||
// variables
|
return nestedPvVariableNames;
|
||||||
// The view's locals needs to have a full set of variable names at construction time
|
}
|
||||||
// in order to prevent new variables from being set later in the lifecycle. Since we don't want
|
|
||||||
// to actually create variable bindings for the $implicit bindings, add to the
|
|
||||||
// protoLocals manually.
|
|
||||||
MapWrapper.forEach(renderElementBinder.variableBindings, (mappedName, varName) => {
|
|
||||||
MapWrapper.set(protoView.protoLocals, mappedName, null);
|
|
||||||
});
|
|
||||||
return elBinder;
|
|
||||||
}
|
|
||||||
|
|
||||||
_bindDirectiveEvents(protoView, elementBinders:List<renderApi.ElementBinder>) {
|
function _createVariableNames(parentVariableNames, variableBindings):List {
|
||||||
for (var boundElementIndex = 0; boundElementIndex < elementBinders.length; ++boundElementIndex) {
|
var variableNames = isPresent(parentVariableNames) ? ListWrapper.clone(parentVariableNames) : [];
|
||||||
var dirs = elementBinders[boundElementIndex].directives;
|
MapWrapper.forEach(variableBindings, (local, v) => {
|
||||||
for (var i = 0; i < dirs.length; i++) {
|
ListWrapper.push(variableNames, local);
|
||||||
var directiveBinder = dirs[i];
|
});
|
||||||
|
return variableNames;
|
||||||
|
}
|
||||||
|
|
||||||
// directive events
|
function _createElementBinders(protoView, elementBinders, allDirectiveBindings) {
|
||||||
protoView.bindEvent(directiveBinder.eventBindings, boundElementIndex, i);
|
for (var i=0; i<elementBinders.length; i++) {
|
||||||
|
var renderElementBinder = elementBinders[i];
|
||||||
|
var dirs = elementBinders[i].directives;
|
||||||
|
|
||||||
|
var parentPeiWithDistance = _findParentProtoElementInjectorWithDistance(
|
||||||
|
i, protoView.elementBinders, elementBinders);
|
||||||
|
var directiveBindings = ListWrapper.map(dirs, (dir) => allDirectiveBindings[dir.directiveIndex] );
|
||||||
|
var componentDirectiveBinding = null;
|
||||||
|
if (directiveBindings.length > 0) {
|
||||||
|
if (directiveBindings[0].metadata.type === renderApi.DirectiveMetadata.COMPONENT_TYPE) {
|
||||||
|
componentDirectiveBinding = directiveBindings[0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
var protoElementInjector = _createProtoElementInjector(
|
||||||
|
i, parentPeiWithDistance, renderElementBinder, componentDirectiveBinding, directiveBindings);
|
||||||
|
|
||||||
|
_createElementBinder(protoView, i, renderElementBinder, protoElementInjector, componentDirectiveBinding);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function _findParentProtoElementInjectorWithDistance(binderIndex, elementBinders, renderElementBinders) {
|
||||||
|
var distance = 0;
|
||||||
|
do {
|
||||||
|
var renderElementBinder = renderElementBinders[binderIndex];
|
||||||
|
binderIndex = renderElementBinder.parentIndex;
|
||||||
|
if (binderIndex !== -1) {
|
||||||
|
distance += renderElementBinder.distanceToParent;
|
||||||
|
var elementBinder = elementBinders[binderIndex];
|
||||||
|
if (isPresent(elementBinder.protoElementInjector)) {
|
||||||
|
return new ParentProtoElementInjectorWithDistance(elementBinder.protoElementInjector, distance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (binderIndex !== -1);
|
||||||
|
return new ParentProtoElementInjectorWithDistance(null, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _createProtoElementInjector(binderIndex, parentPeiWithDistance, renderElementBinder, componentDirectiveBinding, directiveBindings) {
|
||||||
|
var protoElementInjector = null;
|
||||||
|
// Create a protoElementInjector for any element that either has bindings *or* has one
|
||||||
|
// or more var- defined. Elements with a var- defined need a their own element injector
|
||||||
|
// so that, when hydrating, $implicit can be set to the element.
|
||||||
|
var hasVariables = MapWrapper.size(renderElementBinder.variableBindings) > 0;
|
||||||
|
if (directiveBindings.length > 0 || hasVariables) {
|
||||||
|
protoElementInjector = new ProtoElementInjector(
|
||||||
|
parentPeiWithDistance.protoElementInjector, binderIndex,
|
||||||
|
directiveBindings,
|
||||||
|
isPresent(componentDirectiveBinding), parentPeiWithDistance.distance
|
||||||
|
);
|
||||||
|
protoElementInjector.attributes = renderElementBinder.readAttributes;
|
||||||
|
if (hasVariables) {
|
||||||
|
protoElementInjector.exportComponent = isPresent(componentDirectiveBinding);
|
||||||
|
protoElementInjector.exportElement = isBlank(componentDirectiveBinding);
|
||||||
|
|
||||||
|
// experiment
|
||||||
|
var exportImplicitName = MapWrapper.get(renderElementBinder.variableBindings, '\$implicit');
|
||||||
|
if (isPresent(exportImplicitName)) {
|
||||||
|
protoElementInjector.exportImplicitName = exportImplicitName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return protoElementInjector;
|
||||||
|
}
|
||||||
|
|
||||||
|
function _createElementBinder(protoView, boundElementIndex, renderElementBinder, protoElementInjector, componentDirectiveBinding) {
|
||||||
|
var parent = null;
|
||||||
|
if (renderElementBinder.parentIndex !== -1) {
|
||||||
|
parent = protoView.elementBinders[renderElementBinder.parentIndex];
|
||||||
|
}
|
||||||
|
var elBinder = protoView.bindElement(
|
||||||
|
parent,
|
||||||
|
renderElementBinder.distanceToParent,
|
||||||
|
protoElementInjector,
|
||||||
|
componentDirectiveBinding
|
||||||
|
);
|
||||||
|
protoView.bindEvent(renderElementBinder.eventBindings, boundElementIndex, -1);
|
||||||
|
// variables
|
||||||
|
// The view's locals needs to have a full set of variable names at construction time
|
||||||
|
// in order to prevent new variables from being set later in the lifecycle. Since we don't want
|
||||||
|
// to actually create variable bindings for the $implicit bindings, add to the
|
||||||
|
// protoLocals manually.
|
||||||
|
MapWrapper.forEach(renderElementBinder.variableBindings, (mappedName, varName) => {
|
||||||
|
MapWrapper.set(protoView.protoLocals, mappedName, null);
|
||||||
|
});
|
||||||
|
return elBinder;
|
||||||
|
}
|
||||||
|
|
||||||
|
function _bindDirectiveEvents(protoView, elementBinders:List<renderApi.ElementBinder>) {
|
||||||
|
for (var boundElementIndex = 0; boundElementIndex < elementBinders.length; ++boundElementIndex) {
|
||||||
|
var dirs = elementBinders[boundElementIndex].directives;
|
||||||
|
for (var i = 0; i < dirs.length; i++) {
|
||||||
|
var directiveBinder = dirs[i];
|
||||||
|
|
||||||
|
// directive events
|
||||||
|
protoView.bindEvent(directiveBinder.eventBindings, boundElementIndex, i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class RenderProtoViewWithIndex {
|
class RenderProtoViewWithIndex {
|
||||||
renderProtoView:renderApi.ProtoViewDto;
|
renderProtoView:renderApi.ProtoViewDto;
|
||||||
index:number;
|
index:number;
|
||||||
|
|
|
@ -17,7 +17,7 @@ import {isBlank} from 'angular2/src/facade/lang';
|
||||||
import {MapWrapper} from 'angular2/src/facade/collection';
|
import {MapWrapper} from 'angular2/src/facade/collection';
|
||||||
|
|
||||||
import {ChangeDetection, ChangeDetectorDefinition} from 'angular2/change_detection';
|
import {ChangeDetection, ChangeDetectorDefinition} from 'angular2/change_detection';
|
||||||
import {ProtoViewFactory} from 'angular2/src/core/compiler/proto_view_factory';
|
import {ProtoViewFactory, getChangeDetectorDefinitions} from 'angular2/src/core/compiler/proto_view_factory';
|
||||||
import {Component, Directive} from 'angular2/src/core/annotations_impl/annotations';
|
import {Component, Directive} from 'angular2/src/core/annotations_impl/annotations';
|
||||||
import {DirectiveResolver} from 'angular2/src/core/compiler/directive_resolver';
|
import {DirectiveResolver} from 'angular2/src/core/compiler/directive_resolver';
|
||||||
import {DirectiveBinding} from 'angular2/src/core/compiler/element_injector';
|
import {DirectiveBinding} from 'angular2/src/core/compiler/element_injector';
|
||||||
|
@ -45,7 +45,7 @@ export function main() {
|
||||||
|
|
||||||
it('should create a ChangeDetectorDefinition for the root render proto view', () => {
|
it('should create a ChangeDetectorDefinition for the root render proto view', () => {
|
||||||
var renderPv = createRenderProtoView();
|
var renderPv = createRenderProtoView();
|
||||||
var defs = protoViewFactory.getChangeDetectorDefinitions(bindDirective(MainComponent).metadata,
|
var defs = getChangeDetectorDefinitions(bindDirective(MainComponent).metadata,
|
||||||
renderPv, []);
|
renderPv, []);
|
||||||
expect(defs.length).toBe(1);
|
expect(defs.length).toBe(1);
|
||||||
expect(defs[0].id).toEqual('MainComponent_comp_0');
|
expect(defs[0].id).toEqual('MainComponent_comp_0');
|
||||||
|
|
Loading…
Reference in New Issue