refactor(view): change view to pass all bindings to proto change detector at once

This commit is contained in:
vsavkin
2015-03-11 21:43:22 -07:00
parent 1adb23d222
commit 3273adade5
7 changed files with 93 additions and 83 deletions
@@ -45,36 +45,44 @@ import {
export class ProtoChangeDetector {
addAst(ast:AST, bindingMemento:any, directiveMemento:any = null){}
instantiate(dispatcher:any):ChangeDetector{
instantiate(dispatcher:any, bindingRecords:List):ChangeDetector{
return null;
}
}
export class BindingRecord {
ast:AST;
bindingMemento:any;
directiveMemento:any;
constructor(ast:AST, bindingMemento:any, directiveMemento:any) {
this.ast = ast;
this.bindingMemento = bindingMemento;
this.directiveMemento = directiveMemento;
}
}
export class DynamicProtoChangeDetector extends ProtoChangeDetector {
_records:List<ProtoRecord>;
_recordBuilder:ProtoRecordBuilder;
_pipeRegistry:PipeRegistry;
_records:List<ProtoRecord>;
constructor(pipeRegistry:PipeRegistry) {
super();
this._pipeRegistry = pipeRegistry;
this._records = null;
this._recordBuilder = new ProtoRecordBuilder();
}
addAst(ast:AST, bindingMemento:any, directiveMemento:any = null) {
this._recordBuilder.addAst(ast, bindingMemento, directiveMemento);
}
instantiate(dispatcher:any) {
this._createRecordsIfNecessary();
instantiate(dispatcher:any, bindingRecords:List) {
this._createRecordsIfNecessary(bindingRecords);
return new DynamicChangeDetector(dispatcher, this._pipeRegistry, this._records);
}
_createRecordsIfNecessary() {
_createRecordsIfNecessary(bindingRecords:List) {
if (isBlank(this._records)) {
var records = this._recordBuilder.records;
this._records = coalesce(records);
var recordBuilder = new ProtoRecordBuilder();
ListWrapper.forEach(bindingRecords, (r) => {
recordBuilder.addAst(r.ast, r.bindingMemento, r.directiveMemento);
});
this._records = coalesce(recordBuilder.records);
}
}
}
@@ -82,29 +90,27 @@ export class DynamicProtoChangeDetector extends ProtoChangeDetector {
var _jitProtoChangeDetectorClassCounter:number = 0;
export class JitProtoChangeDetector extends ProtoChangeDetector {
_factory:Function;
_recordBuilder:ProtoRecordBuilder;
_pipeRegistry;
constructor(pipeRegistry) {
super();
this._pipeRegistry = pipeRegistry;
this._factory = null;
this._recordBuilder = new ProtoRecordBuilder();
}
addAst(ast:AST, bindingMemento:any, directiveMemento:any = null) {
this._recordBuilder.addAst(ast, bindingMemento, directiveMemento);
}
instantiate(dispatcher:any) {
this._createFactoryIfNecessary();
instantiate(dispatcher:any, bindingRecords:List) {
this._createFactoryIfNecessary(bindingRecords);
return this._factory(dispatcher, this._pipeRegistry);
}
_createFactoryIfNecessary() {
_createFactoryIfNecessary(bindingRecords:List) {
if (isBlank(this._factory)) {
var recordBuilder = new ProtoRecordBuilder();
ListWrapper.forEach(bindingRecords, (r) => {
recordBuilder.addAst(r.ast, r.bindingMemento, r.directiveMemento);
});
var c = _jitProtoChangeDetectorClassCounter++;
var records = coalesce(this._recordBuilder.records);
var records = coalesce(recordBuilder.records);
var typeName = `ChangeDetector${c}`;
this._factory = new ChangeDetectorJITGenerator(typeName, records).generate();
}
+19 -14
View File
@@ -1,8 +1,8 @@
import {DOM} from 'angular2/src/dom/dom_adapter';
import {Promise} from 'angular2/src/facade/async';
import {ListWrapper, MapWrapper, Map, StringMapWrapper, List} from 'angular2/src/facade/collection';
import {AST, ContextWithVariableBindings, ChangeDispatcher, ProtoChangeDetector, ChangeDetector, ChangeRecord}
from 'angular2/change_detection';
import {AST, ContextWithVariableBindings, ChangeDispatcher, ProtoChangeDetector, ChangeDetector,
ChangeRecord, BindingRecord} from 'angular2/change_detection';
import {ProtoElementInjector, ElementInjector, PreBuiltObjects} from './element_injector';
import {BindingPropagationConfig} from './binding_propagation_config';
@@ -46,10 +46,10 @@ export class View {
context: any;
contextWithLocals:ContextWithVariableBindings;
constructor(proto:ProtoView, nodes:List, protoChangeDetector:ProtoChangeDetector, protoContextLocals:Map) {
constructor(proto:ProtoView, nodes:List, protoContextLocals:Map) {
this.proto = proto;
this.nodes = nodes;
this.changeDetector = protoChangeDetector.instantiate(this);
this.changeDetector = null;
this.elementInjectors = null;
this.rootElementInjectors = null;
this.textNodes = null;
@@ -63,8 +63,9 @@ export class View {
: null;
}
init(elementInjectors:List, rootElementInjectors:List, textNodes: List, bindElements:List,
init(changeDetector:ChangeDetector, elementInjectors:List, rootElementInjectors:List, textNodes: List, bindElements:List,
viewContainers:List, preBuiltObjects:List, componentChildViews:List) {
this.changeDetector = changeDetector;
this.elementInjectors = elementInjectors;
this.rootElementInjectors = rootElementInjectors;
this.textNodes = textNodes;
@@ -294,12 +295,13 @@ export class ProtoView {
_viewPool: ViewPool;
stylePromises: List<Promise>;
// List<Map<eventName, handler>>, indexed by binder index
eventHandlers: List;
eventHandlers:List;
bindingRecords:List;
constructor(
template,
protoChangeDetector:ProtoChangeDetector,
shadowDomStrategy: ShadowDomStrategy) {
shadowDomStrategy:ShadowDomStrategy) {
this.element = template;
this.elementBinders = [];
this.variableBindings = MapWrapper.create();
@@ -315,6 +317,7 @@ export class ProtoView {
this._viewPool = new ViewPool(VIEW_POOL_CAPACITY);
this.stylePromises = [];
this.eventHandlers = [];
this.bindingRecords = [];
}
// TODO(rado): hostElementInjector should be moved to hydrate phase.
@@ -357,7 +360,9 @@ export class ProtoView {
viewNodes = [rootElementClone];
}
var view = new View(this, viewNodes, this.protoChangeDetector, this.protoContextLocals);
var view = new View(this, viewNodes, this.protoContextLocals);
var changeDetector = this.protoChangeDetector.instantiate(view, this.bindingRecords);
var binders = this.elementBinders;
var elementInjectors = ListWrapper.createFixedSize(binders.length);
var eventHandlers = ListWrapper.createFixedSize(binders.length);
@@ -413,12 +418,12 @@ export class ProtoView {
if (isPresent(binder.componentDirective)) {
var strategy = this.shadowDomStrategy;
var childView = binder.nestedProtoView.instantiate(elementInjector, eventManager);
view.changeDetector.addChild(childView.changeDetector);
changeDetector.addChild(childView.changeDetector);
lightDom = strategy.constructLightDom(view, childView, element);
strategy.attachTemplate(element, childView);
bindingPropagationConfig = new BindingPropagationConfig(view.changeDetector);
bindingPropagationConfig = new BindingPropagationConfig(changeDetector);
ListWrapper.push(componentChildViews, childView);
}
@@ -454,7 +459,7 @@ export class ProtoView {
this.eventHandlers = eventHandlers;
view.init(elementInjectors, rootElementInjectors, textNodes, elementsWithPropertyBindings,
view.init(changeDetector, elementInjectors, rootElementInjectors, textNodes, elementsWithPropertyBindings,
viewContainers, preBuiltObjects, componentChildViews);
return view;
@@ -519,7 +524,7 @@ export class ProtoView {
}
ListWrapper.push(elBinder.textNodeIndices, indexInParent);
var memento = this.textNodesWithBindingCount++;
this.protoChangeDetector.addAst(expression, memento);
ListWrapper.push(this.bindingRecords, new BindingRecord(expression, memento, null));
}
/**
@@ -532,7 +537,7 @@ export class ProtoView {
this.elementsWithBindingCount++;
}
var memento = new ElementBindingMemento(this.elementsWithBindingCount-1, setterName, setter);
this.protoChangeDetector.addAst(expression, memento);
ListWrapper.push(this.bindingRecords, new BindingRecord(expression, memento, null));
}
/**
@@ -579,7 +584,7 @@ export class ProtoView {
setter
);
var directiveMemento = DirectiveMemento.get(bindingMemento);
this.protoChangeDetector.addAst(expression, bindingMemento, directiveMemento);
ListWrapper.push(this.bindingRecords, new BindingRecord(expression, bindingMemento, directiveMemento));
}
// Create a rootView as if the compiler encountered <rootcmp></rootcmp>,