perf(view): inline and refactor view instantiation and hydration

- Don’t convert DOM array into JS array via `Array.slice`
- Inline static methods for instantiation and hydration
- Misc cleanup

Closes #291
This commit is contained in:
Tobias Bosch
2014-12-09 10:31:19 -08:00
parent 8acf9fb609
commit 3ec3d5e084
11 changed files with 223 additions and 254 deletions

View File

@ -12,7 +12,7 @@ import {NgElement} from 'core/dom/element';
//TODO: vsavkin: use a spy object
class DummyView extends View {
constructor() {
super(null, null, null, null, null, null, new ProtoRecordRange());
super(null, null, new ProtoRecordRange(), MapWrapper.create());
}
}

View File

@ -32,12 +32,6 @@ export function main() {
var parser = new Parser(new Lexer());
return new CompilePipeline([
new MockStep((parent, current, control) => {
if (isPresent(current.element.getAttribute('viewroot'))) {
current.isViewRoot = true;
current.inheritedProtoView = new ProtoView(current.element, new ProtoRecordRange());
} else if (isPresent(parent)) {
current.inheritedProtoView = parent.inheritedProtoView;
}
var hasBinding = false;
if (isPresent(current.element.getAttribute('text-binding'))) {
MapWrapper.forEach(textNodeBindings, (v,k) => {
@ -72,6 +66,12 @@ export function main() {
current.hasBindings = true;
DOM.addClass(current.element, 'ng-binding');
}
if (isPresent(current.element.getAttribute('viewroot'))) {
current.isViewRoot = true;
current.inheritedProtoView = new ProtoView(current.element, new ProtoRecordRange());
} else if (isPresent(parent)) {
current.inheritedProtoView = parent.inheritedProtoView;
}
}), new ElementBinderBuilder()
]);
}
@ -159,22 +159,22 @@ export function main() {
it('should bind element properties', () => {
var propertyBindings = MapWrapper.createFromStringMap({
'elprop1': 'prop1',
'elprop2': 'prop2'
'value': 'prop1',
'hidden': 'prop2'
});
var pipeline = createPipeline({propertyBindings: propertyBindings});
var results = pipeline.process(createElement('<div viewroot prop-binding></div>'));
var results = pipeline.process(createElement('<input viewroot prop-binding>'));
var pv = results[0].inheritedProtoView;
expect(pv.elementBinders[0].hasElementPropertyBindings).toBe(true);
instantiateView(pv);
evalContext.prop1 = 'a';
evalContext.prop2 = 'b';
evalContext.prop2 = false;
changeDetector.detectChanges();
expect(DOM.getProperty(view.nodes[0], 'elprop1')).toEqual('a');
expect(DOM.getProperty(view.nodes[0], 'elprop2')).toEqual('b');
expect(view.nodes[0].value).toEqual('a');
expect(view.nodes[0].hidden).toEqual(false);
});
it('should bind events', () => {

View File

@ -105,7 +105,7 @@ export function main() {
it('should collect property bindings on the root element if it has the ng-binding class', () => {
var pv = new ProtoView(templateAwareCreateElement('<div [prop]="a" class="ng-binding"></div>'), new ProtoRecordRange());
pv.bindElement(null);
pv.bindElementProperty('prop', parser.parseBinding('a'));
pv.bindElementProperty(parser.parseBinding('a').ast, 'prop', reflector.setter('prop'));
var view = pv.instantiate(null);
view.hydrate(null, null, null);
@ -117,7 +117,7 @@ export function main() {
var pv = new ProtoView(templateAwareCreateElement('<div><span></span><span class="ng-binding"></span></div>'),
new ProtoRecordRange());
pv.bindElement(null);
pv.bindElementProperty('a', parser.parseBinding('b'));
pv.bindElementProperty(parser.parseBinding('b').ast, 'a', reflector.setter('a'));
var view = pv.instantiate(null);
view.hydrate(null, null, null);
@ -159,9 +159,10 @@ export function main() {
describe('inplace instantiation', () => {
it('should be supported.', () => {
var template = createElement('<div></div>')
var view = new ProtoView(template, new ProtoRecordRange())
.instantiate(null, true);
var template = createElement('<div></div>');
var pv = new ProtoView(template, new ProtoRecordRange());
pv.instantiateInPlace = true;
var view = pv.instantiate(null);
view.hydrate(null, null, null);
expect(view.nodes[0]).toBe(template);
});
@ -369,7 +370,7 @@ export function main() {
var pv = new ProtoView(createElement('<div class="ng-binding"></div>'),
new ProtoRecordRange());
pv.bindElement(null);
pv.bindElementProperty('id', parser.parseBinding('foo'));
pv.bindElementProperty(parser.parseBinding('foo').ast, 'id', reflector.setter('id'));
createViewAndChangeDetector(pv);
ctx.foo = 'buz';
@ -437,14 +438,14 @@ export function main() {
it('should create the root component when instantiated', () => {
var rootProtoView = ProtoView.createRootProtoView(pv, el, someComponentDirective);
var view = rootProtoView.instantiate(null, true);
var view = rootProtoView.instantiate(null);
view.hydrate(new Injector([]), null, null);
expect(view.rootElementInjectors[0].get(SomeComponent)).not.toBe(null);
});
it('should inject the protoView into the shadowDom', () => {
var rootProtoView = ProtoView.createRootProtoView(pv, el, someComponentDirective);
var view = rootProtoView.instantiate(null, true);
var view = rootProtoView.instantiate(null);
view.hydrate(new Injector([]), null, null);
expect(el.shadowRoot.childNodes[0].childNodes[0].nodeValue).toEqual('hi');
});

View File

@ -14,7 +14,9 @@ function createElement(html) {
}
function createView(nodes) {
return new View(null, nodes, [], [], [], [], new ProtoRecordRange());
var view = new View(null, nodes, new ProtoRecordRange(), MapWrapper.create());
view.init([], [], [], [], [], [], []);
return view;
}
export function main() {