From 811b46073af9fe2f7e353ce1b811898c1557bad8 Mon Sep 17 00:00:00 2001 From: James deBoer Date: Thu, 6 Mar 2014 11:46:43 -0800 Subject: [PATCH] feat(element binder): Make ElementBinder non-recursive and create an external tree --- lib/core_dom/compiler.dart | 18 ++++++++++-------- lib/core_dom/element_binder.dart | 23 +++++++++++++++++------ lib/core_dom/view_factory.dart | 14 ++++++++------ 3 files changed, 35 insertions(+), 20 deletions(-) diff --git a/lib/core_dom/compiler.dart b/lib/core_dom/compiler.dart index 56a91275c..62c49a8b6 100644 --- a/lib/core_dom/compiler.dart +++ b/lib/core_dom/compiler.dart @@ -7,20 +7,20 @@ class Compiler implements Function { Compiler(this._perf, this._expando); - List _compileView(NodeCursor domCursor, NodeCursor templateCursor, + List _compileView(NodeCursor domCursor, NodeCursor templateCursor, ElementBinder existingElementBinder, DirectiveMap directives) { if (domCursor.current == null) return null; - List elementBinders = null; // don't pre-create to create sparse tree and prevent GC pressure. + List elementBinders = null; // don't pre-create to create sparse tree and prevent GC pressure. do { + var subtrees, binder; + ElementBinder elementBinder = existingElementBinder == null ? directives.selector(domCursor.current) : existingElementBinder; - elementBinder.offsetIndex = templateCursor.index; - if (elementBinder.hasTemplate) { elementBinder.templateViewFactory = compileTransclusion( domCursor, templateCursor, @@ -31,7 +31,7 @@ class Compiler implements Function { if (domCursor.descend()) { templateCursor.descend(); - elementBinder.childElementBinders = + subtrees = _compileView(domCursor, templateCursor, null, directives); domCursor.ascend(); @@ -39,10 +39,12 @@ class Compiler implements Function { } } - if (elementBinder.isUseful) { - if (elementBinders == null) elementBinders = []; - elementBinders.add(elementBinder); + if (elementBinder.hasDirectives) { + binder = elementBinder; } + + if (elementBinders == null) elementBinders = []; + elementBinders.add(new ElementBinderTreeRef(templateCursor.index, new ElementBinderTree(binder, subtrees))); } while (templateCursor.moveNext() && domCursor.moveNext()); return elementBinders; diff --git a/lib/core_dom/element_binder.dart b/lib/core_dom/element_binder.dart index 4ef865457..19fbcab4a 100644 --- a/lib/core_dom/element_binder.dart +++ b/lib/core_dom/element_binder.dart @@ -30,8 +30,6 @@ class ElementBinder { ViewFactory templateViewFactory; DirectiveRef component; - var childElementBinders; - var offsetIndex; // Can be either COMPILE_CHILDREN or IGNORE_CHILDREN String childMode = NgAnnotation.COMPILE_CHILDREN; @@ -46,8 +44,6 @@ class ElementBinder { decorators = other.decorators; component = other.component; - childElementBinders = other.childElementBinders; - offsetIndex = other.offsetIndex; childMode = other.childMode; } @@ -92,8 +88,8 @@ class ElementBinder { return decorators; } - bool get isUseful { - return (_usableDirectiveRefs != null && _usableDirectiveRefs.length != 0) || childElementBinders != null; + bool get hasDirectives { + return (_usableDirectiveRefs != null && _usableDirectiveRefs.length != 0); } // DI visibility callback allowing node-local visibility. @@ -378,3 +374,18 @@ class ElementBinder { }); } } + + +// Used for walking the DOM +class ElementBinderTreeRef { + final int offsetIndex; + final ElementBinderTree subtree; + + ElementBinderTreeRef(this.offsetIndex, this.subtree); +} +class ElementBinderTree { + ElementBinder binder; + List subtrees; + + ElementBinderTree(this.binder, this.subtrees); +} diff --git a/lib/core_dom/view_factory.dart b/lib/core_dom/view_factory.dart index 1fcdb417a..060d7c0ef 100644 --- a/lib/core_dom/view_factory.dart +++ b/lib/core_dom/view_factory.dart @@ -24,13 +24,13 @@ class BoundViewFactory { * [Compiler] as a result of compiling a template. */ class ViewFactory implements Function { - final List elementBinders; + final List elementBinders; final List templateElements; final Profiler _perf; final Expando _expando; ViewFactory(this.templateElements, this.elementBinders, this._perf, this._expando) { - assert(elementBinders.forEach((ElementBinder eb) { assert(eb is ElementBinder); }) != true); + assert(elementBinders.forEach((ElementBinderTreeRef eb) { assert(eb is ElementBinderTreeRef); }) != true); } BoundViewFactory bind(Injector injector) => @@ -57,7 +57,9 @@ class ViewFactory implements Function { var eb = elementBinders[i]; int index = eb.offsetIndex; - List childElementBinders = eb.childElementBinders; + ElementBinderTree tree = eb.subtree; + + //List childElementBinders = eb.childElementBinders; int nodeListIndex = index + preRenderedIndexOffset; dom.Node node = nodeList[nodeListIndex]; @@ -73,10 +75,10 @@ class ViewFactory implements Function { parentNode.append(node); } - var childInjector = eb.bind(view, parentInjector, node); + var childInjector = tree.binder != null ? tree.binder.bind(view, parentInjector, node) : parentInjector; - if (childElementBinders != null) { - _link(view, node.nodes, childElementBinders, childInjector); + if (tree.subtrees != null) { + _link(view, node.nodes, tree.subtrees, childInjector); } if (fakeParent) {