diff --git a/modules/benchmarks/src/element_injector/instantiate_benchmark.js b/modules/benchmarks/src/element_injector/instantiate_benchmark.js index ac8edae8ab..b6bb3d6980 100644 --- a/modules/benchmarks/src/element_injector/instantiate_benchmark.js +++ b/modules/benchmarks/src/element_injector/instantiate_benchmark.js @@ -8,9 +8,9 @@ export function run () { var appInjector = new Injector([]); var bindings = [A, B, C]; - var proto = new ProtoElementInjector(null, bindings); + var proto = new ProtoElementInjector(null, 0, bindings); for (var i = 0; i < ITERATIONS; ++i) { - var ei = proto.instantiate({view:null}); + var ei = proto.instantiate({view:null, parentElementInjector: null}); ei.instantiateDirectives(appInjector); } } diff --git a/modules/benchmarks/src/element_injector/instantiate_benchmark_codegen.js b/modules/benchmarks/src/element_injector/instantiate_benchmark_codegen.js index 1d326707e8..94d9b39dd1 100644 --- a/modules/benchmarks/src/element_injector/instantiate_benchmark_codegen.js +++ b/modules/benchmarks/src/element_injector/instantiate_benchmark_codegen.js @@ -16,9 +16,9 @@ export function run () { ], false)]; - var proto = new ProtoElementInjector(null, bindings); + var proto = new ProtoElementInjector(null, 0, bindings); for (var i = 0; i < ITERATIONS; ++i) { - var ei = proto.instantiate({view:null}); + var ei = proto.instantiate({view:null, parentElementInjector: null}); ei.instantiateDirectives(appInjector); } } diff --git a/modules/benchmarks/src/element_injector/instantiate_directive_benchmark.js b/modules/benchmarks/src/element_injector/instantiate_directive_benchmark.js index 7e2eff9c49..8dc6d4a71f 100644 --- a/modules/benchmarks/src/element_injector/instantiate_directive_benchmark.js +++ b/modules/benchmarks/src/element_injector/instantiate_directive_benchmark.js @@ -8,8 +8,8 @@ export function run () { var appInjector = new Injector([]); var bindings = [A, B, C]; - var proto = new ProtoElementInjector(null, bindings); - var ei = proto.instantiate({view:null}); + var proto = new ProtoElementInjector(null, 0, bindings); + var ei = proto.instantiate({view:null, parentElementInjector: null}); for (var i = 0; i < ITERATIONS; ++i) { ei.clearDirectives(); diff --git a/modules/core/src/compiler/element_injector.js b/modules/core/src/compiler/element_injector.js index b41516aaaa..8169eda863 100644 --- a/modules/core/src/compiler/element_injector.js +++ b/modules/core/src/compiler/element_injector.js @@ -93,39 +93,7 @@ ElementInjector (ElementModule): PERF BENCHMARK: http://www.williambrownstreet.net/blog/2014/04/faster-angularjs-rendering-angularjs-and-reactjs/ */ -export class ProtoElementInjector extends TreeNode { - /** - parent:ProtoDirectiveInjector; - next:ProtoDirectiveInjector; - prev:ProtoDirectiveInjector; - head:ProtoDirectiveInjector; - tail:ProtoDirectiveInjector; - DirectiveInjector cloningInstance; - KeyMap keyMap; - /// Because DI tree is sparse, this shows how far away is the Parent DI - parentDistance:int = 1; /// 1 for non-sparse/normal depth. - - cKey:int; cFactory:Function; cParams:List; - _keyId0:int; factory0:Function; params0:List; - _keyId1:int; factory1:Function; params1:List; - _keyId2:int; factory2:Function; params2:List; - _keyId3:int; factory3:Function; params3:List; - _keyId4:int; factory4:Function; params4:List; - _keyId5:int; factory5:Function; params5:List; - _keyId6:int; factory6:Function; params6:List; - _keyId7:int; factory7:Function; params7:List; - _keyId8:int; factory8:Function; params8:List; - _keyId9:int; factory9:Function; params9:List; - - query_keyId0:int; - query_keyId1:int; - - textNodes:List; - events:Map; - - elementInjector:ElementInjector; - */ - @FIELD('_elementInjector:ElementInjector') +export class ProtoElementInjector { @FIELD('_binding0:Binding') @FIELD('_binding1:Binding') @FIELD('_binding2:Binding') @@ -146,10 +114,11 @@ export class ProtoElementInjector extends TreeNode { @FIELD('_key7:int') @FIELD('_key8:int') @FIELD('_key9:int') - constructor(parent:ProtoElementInjector, bindings:List) { - super(parent); - - this._elementInjector = null; + @FIELD('final parent:ProtoElementInjector') + @FIELD('final index:int') + constructor(parent:ProtoElementInjector, index:int, bindings:List) { + this.parent = parent; + this.index = index; this._binding0 = null; this._keyId0 = null; this._binding1 = null; this._keyId1 = null; @@ -179,15 +148,12 @@ export class ProtoElementInjector extends TreeNode { } } - instantiate({view}):ElementInjector { - var p = this._parent; - var parentElementInjector = p === null ? null : p._elementInjector; - this._elementInjector = new ElementInjector({ + instantiate({view, parentElementInjector}):ElementInjector { + return new ElementInjector({ proto: this, parent: parentElementInjector, view: view }); - return this._elementInjector; } _createBinding(bindingOrType) { @@ -198,10 +164,6 @@ export class ProtoElementInjector extends TreeNode { return new Binding(b.key, b.factory, deps, b.providedAsPromise); } - clearElementInjector() { - this._elementInjector = null; - } - get hasBindings():boolean { return isPresent(this._binding0); } diff --git a/modules/core/src/compiler/view.js b/modules/core/src/compiler/view.js index f489ef329b..7ae5ed6282 100644 --- a/modules/core/src/compiler/view.js +++ b/modules/core/src/compiler/view.js @@ -99,13 +99,9 @@ export class ProtoView { static _createElementInjectors(elements, binders) { var injectors = ListWrapper.createFixedSize(binders.length); for (var i = 0; i < binders.length; ++i) { - injectors[i] = ProtoView._createElementInjector( - elements[i], binders[i].protoElementInjector); - } - // Cannot be rolled into loop above, because parentInjector pointers need - // to be set on the children. - for (var i = 0; i < binders.length; ++i) { - binders[i].protoElementInjector.clearElementInjector(); + var proto = binders[i].protoElementInjector; + var parentElementInjector = isPresent(proto.parent) ? injectors[proto.parent.index] : null; + injectors[i] = ProtoView._createElementInjector(elements[i], parentElementInjector, proto); } return injectors; } @@ -117,9 +113,9 @@ export class ProtoView { } } - static _createElementInjector(element, proto) { + static _createElementInjector(element, parent:ElementInjector, proto:ProtoElementInjector) { //TODO: vsavkin: pass element to `proto.instantiate()` once https://github.com/angular/angular/pull/98 is merged - return proto.hasBindings ? proto.instantiate({view:null}) : null; + return proto.hasBindings ? proto.instantiate({view:null, parentElementInjector:parent}) : null; } static _rootElementInjectors(injectors) { diff --git a/modules/core/test/compiler/element_injector_spec.js b/modules/core/test/compiler/element_injector_spec.js index 99685a03ac..9f5fada26b 100644 --- a/modules/core/test/compiler/element_injector_spec.js +++ b/modules/core/test/compiler/element_injector_spec.js @@ -70,8 +70,8 @@ export function main() { if (isBlank(appInjector)) appInjector = new Injector([]); if (isBlank(props)) props = {}; - var proto = new ProtoElementInjector(null, bindings); - var inj = proto.instantiate({view: props["view"]}); + var proto = new ProtoElementInjector(null, 0, bindings); + var inj = proto.instantiate({view: props["view"], parentElementInjector:null}); inj.instantiateDirectives(appInjector); return inj; } @@ -79,41 +79,27 @@ export function main() { function parentChildInjectors(parentBindings, childBindings) { var inj = new Injector([]); - var protoParent = new ProtoElementInjector(null, parentBindings); - var parent = protoParent.instantiate({view: null}); + var protoParent = new ProtoElementInjector(null, 0, parentBindings); + var parent = protoParent.instantiate({view: null, parentElementInjector: null}); parent.instantiateDirectives(inj); - var protoChild = new ProtoElementInjector(protoParent, childBindings); - var child = protoChild.instantiate({view: null}); + var protoChild = new ProtoElementInjector(protoParent, 1, childBindings); + var child = protoChild.instantiate({view: null, parentElementInjector: parent}); child.instantiateDirectives(inj); return child; } describe("ElementInjector", function () { - describe("proto injectors", function () { - it("should construct a proto tree", function () { - var p = new ProtoElementInjector(null, []); - var c1 = new ProtoElementInjector(p, []); - var c2 = new ProtoElementInjector(p, []); - - expect(humanize(p, [ - [p, 'parent'], - [c1, 'child1'], - [c2, 'child2'] - ])).toEqual(["parent", ["child1", "child2"]]); - }); - }); - describe("instantiate", function () { it("should create an element injector", function () { - var protoParent = new ProtoElementInjector(null, []); - var protoChild1 = new ProtoElementInjector(protoParent, []); - var protoChild2 = new ProtoElementInjector(protoParent, []); + var protoParent = new ProtoElementInjector(null, 0, []); + var protoChild1 = new ProtoElementInjector(protoParent, 1, []); + var protoChild2 = new ProtoElementInjector(protoParent, 2, []); - var p = protoParent.instantiate({view: null}); - var c1 = protoChild1.instantiate({view: null}); - var c2 = protoChild2.instantiate({view: null}); + var p = protoParent.instantiate({view: null, parentElementInjector: null}); + var c1 = protoChild1.instantiate({view: null, parentElementInjector: p}); + var c2 = protoChild2.instantiate({view: null, parentElementInjector: p}); expect(humanize(p, [ [p, 'parent'], @@ -125,12 +111,12 @@ export function main() { describe("hasBindings", function () { it("should be true when there are bindings", function () { - var p = new ProtoElementInjector(null, [Directive]); + var p = new ProtoElementInjector(null, 0, [Directive]); expect(p.hasBindings).toBeTruthy(); }); it("should be false otherwise", function () { - var p = new ProtoElementInjector(null, []); + var p = new ProtoElementInjector(null, 0, []); expect(p.hasBindings).toBeFalsy(); }); }); diff --git a/modules/core/test/compiler/view_spec.js b/modules/core/test/compiler/view_spec.js index 9cd3bcabc7..9f4c3390ab 100644 --- a/modules/core/test/compiler/view_spec.js +++ b/modules/core/test/compiler/view_spec.js @@ -34,14 +34,14 @@ export function main() { ''; function templateElementBinders() { - var sectionPI = new ElementBinder(new ProtoElementInjector(null, []), + var sectionPI = new ElementBinder(new ProtoElementInjector(null, 0, []), [0], false); var divPI = new ElementBinder(new ProtoElementInjector( - sectionPI.protoElementInjector, [Directive]), [], false); + sectionPI.protoElementInjector, 1, [Directive]), [], false); var spanPI = new ElementBinder(new ProtoElementInjector( - divPI.protoElementInjector, []), [], true); + divPI.protoElementInjector, 2, []), [], true); return [sectionPI, divPI, spanPI]; } @@ -76,9 +76,9 @@ export function main() { ''); var sectionPI = new ElementBinder(new ProtoElementInjector( - null, [Directive]), [], false); + null, 0, [Directive]), [], false); var divPI = new ElementBinder(new ProtoElementInjector( - sectionPI.protoElementInjector, [Directive]), [], false); + sectionPI.protoElementInjector, 1, [Directive]), [], false); var pv = new ProtoView(template, [sectionPI, divPI], new ProtoWatchGroup(), false);