perf(render): precompute # bound text nodes and root nodes in `DomProtoView`

This commit is contained in:
Tobias Bosch 2015-06-09 11:57:50 -07:00
parent 9cd510abaa
commit 24e647e0f7
3 changed files with 17 additions and 10 deletions

View File

@ -102,7 +102,7 @@ class Html5LibDomAdapter implements DomAdapter {
throw 'not implemented'; throw 'not implemented';
} }
content(node) { content(node) {
throw 'not implemented'; return node;
} }
firstChild(el) => el is NodeList ? el.first : el.firstChild; firstChild(el) => el is NodeList ? el.first : el.firstChild;

View File

@ -224,13 +224,11 @@ export class DomRenderer extends Renderer {
rootElementClone = DOM.importIntoDoc(DOM.content(protoView.element)); rootElementClone = DOM.importIntoDoc(DOM.content(protoView.element));
elementsWithBindingsDynamic = elementsWithBindingsDynamic =
DOM.querySelectorAll(rootElementClone, NG_BINDING_CLASS_SELECTOR); DOM.querySelectorAll(rootElementClone, NG_BINDING_CLASS_SELECTOR);
var childNode = DOM.firstChild(rootElementClone); viewRootNodes = ListWrapper.createFixedSize(protoView.rootNodeCount);
// TODO(perf): Should be fixed size, since we could pre-compute in in DomProtoView
viewRootNodes = [];
// Note: An explicit loop is the fastest way to convert a DOM array into a JS array! // Note: An explicit loop is the fastest way to convert a DOM array into a JS array!
while (childNode != null) { var childNode = DOM.firstChild(rootElementClone);
ListWrapper.push(viewRootNodes, childNode); for (var i = 0; i < protoView.rootNodeCount; i++, childNode = DOM.nextSibling(childNode)) {
childNode = DOM.nextSibling(childNode); viewRootNodes[i] = childNode;
} }
} else { } else {
rootElementClone = DOM.importIntoDoc(protoView.element); rootElementClone = DOM.importIntoDoc(protoView.element);
@ -239,8 +237,9 @@ export class DomRenderer extends Renderer {
} }
var binders = protoView.elementBinders; var binders = protoView.elementBinders;
var boundTextNodes = []; var boundTextNodes = ListWrapper.createFixedSize(protoView.boundTextNodeCount);
var boundElements = ListWrapper.createFixedSize(binders.length); var boundElements = ListWrapper.createFixedSize(binders.length);
var boundTextNodeIdx = 0;
for (var binderIdx = 0; binderIdx < binders.length; binderIdx++) { for (var binderIdx = 0; binderIdx < binders.length; binderIdx++) {
var binder = binders[binderIdx]; var binder = binders[binderIdx];
@ -261,7 +260,7 @@ export class DomRenderer extends Renderer {
// boundTextNodes // boundTextNodes
var textNodeIndices = binder.textNodeIndices; var textNodeIndices = binder.textNodeIndices;
for (var i = 0; i < textNodeIndices.length; i++) { for (var i = 0; i < textNodeIndices.length; i++) {
ListWrapper.push(boundTextNodes, childNodes[textNodeIndices[i]]); boundTextNodes[boundTextNodeIdx++] = childNodes[textNodeIndices[i]];
} }
// contentTags // contentTags

View File

@ -1,7 +1,7 @@
import {isPresent} from 'angular2/src/facade/lang'; import {isPresent} from 'angular2/src/facade/lang';
import {DOM} from 'angular2/src/dom/dom_adapter'; import {DOM} from 'angular2/src/dom/dom_adapter';
import {List} from 'angular2/src/facade/collection'; import {List, ListWrapper} from 'angular2/src/facade/collection';
import {ElementBinder} from './element_binder'; import {ElementBinder} from './element_binder';
import {NG_BINDING_CLASS} from '../util'; import {NG_BINDING_CLASS} from '../util';
@ -27,6 +27,8 @@ export class DomProtoView {
rootBindingOffset: number; rootBindingOffset: number;
// the number of content tags seen in this or any child proto view. // the number of content tags seen in this or any child proto view.
transitiveContentTagCount: number; transitiveContentTagCount: number;
boundTextNodeCount: number;
rootNodeCount: number;
constructor({elementBinders, element, transitiveContentTagCount}) { constructor({elementBinders, element, transitiveContentTagCount}) {
this.element = element; this.element = element;
@ -35,5 +37,11 @@ export class DomProtoView {
this.isTemplateElement = DOM.isTemplateElement(this.element); this.isTemplateElement = DOM.isTemplateElement(this.element);
this.rootBindingOffset = this.rootBindingOffset =
(isPresent(this.element) && DOM.hasClass(this.element, NG_BINDING_CLASS)) ? 1 : 0; (isPresent(this.element) && DOM.hasClass(this.element, NG_BINDING_CLASS)) ? 1 : 0;
this.boundTextNodeCount =
ListWrapper.reduce(elementBinders, (prevCount: number, elementBinder: ElementBinder) =>
prevCount + elementBinder.textNodeIndices.length,
0);
this.rootNodeCount =
this.isTemplateElement ? DOM.childNodes(DOM.content(this.element)).length : 1;
} }
} }