From 457cbaa39b45409ae6ffd6402a9251dc10970588 Mon Sep 17 00:00:00 2001 From: Victor Berchet Date: Tue, 6 Jan 2015 13:30:48 +0100 Subject: [PATCH] fix(ProtoView): element injector should have either a parent or a host fix #359 --- .../proto_element_injector_builder.js | 9 ++-- modules/core/src/compiler/view.js | 8 ++-- modules/core/test/compiler/view_spec.js | 48 ++++++++++++++++++- 3 files changed, 55 insertions(+), 10 deletions(-) diff --git a/modules/core/src/compiler/pipeline/proto_element_injector_builder.js b/modules/core/src/compiler/pipeline/proto_element_injector_builder.js index 5f8e7c6753..27dd7ffd21 100644 --- a/modules/core/src/compiler/pipeline/proto_element_injector_builder.js +++ b/modules/core/src/compiler/pipeline/proto_element_injector_builder.js @@ -49,13 +49,10 @@ export class ProtoElementInjectorBuilder extends CompileStep { } _getParentProtoElementInjector(parent, current) { - var parentProtoElementInjector = null; - if (current.isViewRoot) { - parentProtoElementInjector = null; - } else if (isPresent(parent)) { - parentProtoElementInjector = parent.inheritedProtoElementInjector; + if (isPresent(parent) && !current.isViewRoot) { + return parent.inheritedProtoElementInjector; } - return parentProtoElementInjector; + return null; } _collectDirectiveBindings(pipelineElement) { diff --git a/modules/core/src/compiler/view.js b/modules/core/src/compiler/view.js index 61c7fcd8f7..c479f269fd 100644 --- a/modules/core/src/compiler/view.js +++ b/modules/core/src/compiler/view.js @@ -309,9 +309,11 @@ export class ProtoView { // elementInjectors and rootElementInjectors var protoElementInjector = binder.protoElementInjector; if (isPresent(protoElementInjector)) { - var parentElementInjector = isPresent(protoElementInjector.parent) ? elementInjectors[protoElementInjector.parent.index] : null; - elementInjector = protoElementInjector.instantiate(parentElementInjector, hostElementInjector); - if (isBlank(parentElementInjector)) { + if (isPresent(protoElementInjector.parent)) { + var parentElementInjector = elementInjectors[protoElementInjector.parent.index]; + elementInjector = protoElementInjector.instantiate(parentElementInjector, null); + } else { + elementInjector = protoElementInjector.instantiate(null, hostElementInjector); ListWrapper.push(rootElementInjectors, elementInjector); } } diff --git a/modules/core/test/compiler/view_spec.js b/modules/core/test/compiler/view_spec.js index 2fd83354e9..257763647d 100644 --- a/modules/core/test/compiler/view_spec.js +++ b/modules/core/test/compiler/view_spec.js @@ -7,8 +7,9 @@ import {Component, Decorator, Template} from 'core/annotations/annotations'; import {OnChange} from 'core/core'; import {Lexer, Parser, ProtoRecordRange, ChangeDetector} from 'change_detection/change_detection'; import {TemplateConfig} from 'core/annotations/template_config'; +import {List} from 'facade/collection'; import {DOM, Element} from 'facade/dom'; -import {FIELD} from 'facade/lang'; +import {int} from 'facade/lang'; import {Injector} from 'di/di'; import {View} from 'core/compiler/view'; import {ViewPort} from 'core/compiler/viewport'; @@ -206,6 +207,36 @@ export function main() { expect(view.elementInjectors[0].get(SomeDirective) instanceof SomeDirective).toBe(true); expect(view.elementInjectors[1].parent).toBe(view.elementInjectors[0]); }); + + it('should not pass the host injector when a parent injector exists', () => { + var pv = new ProtoView(createElement('
'), + new ProtoRecordRange()); + var protoParent = new ProtoElementInjector(null, 0, [SomeDirective]); + pv.bindElement(protoParent); + var testProtoElementInjector = new TestProtoElementInjector(protoParent, 1, [AnotherDirective]); + pv.bindElement(testProtoElementInjector); + + var hostProtoInjector = new ProtoElementInjector(null, 0, []); + var hostInjector = hostProtoInjector.instantiate(null, null); + var view; + expect(() => view = pv.instantiate(hostInjector)).not.toThrow(); + expect(testProtoElementInjector.parentElementInjector).toBe(view.elementInjectors[0]); + expect(testProtoElementInjector.hostElementInjector).toBeNull(); + }); + + it('should pass the host injector when there is no parent injector', () => { + var pv = new ProtoView(createElement('
'), + new ProtoRecordRange()); + pv.bindElement(new ProtoElementInjector(null, 0, [SomeDirective])); + var testProtoElementInjector = new TestProtoElementInjector(null, 1, [AnotherDirective]); + pv.bindElement(testProtoElementInjector); + + var hostProtoInjector = new ProtoElementInjector(null, 0, []); + var hostInjector = hostProtoInjector.instantiate(null, null); + expect(() => pv.instantiate(hostInjector)).not.toThrow(); + expect(testProtoElementInjector.parentElementInjector).toBeNull(); + expect(testProtoElementInjector.hostElementInjector).toBe(hostInjector); + }); }); describe('collect root element injectors', () => { @@ -544,3 +575,18 @@ class MyEvaluationContext { function createElement(html) { return DOM.createTemplate(html).content.firstChild; } + +class TestProtoElementInjector extends ProtoElementInjector { + parentElementInjector: ElementInjector; + hostElementInjector: ElementInjector; + + constructor(parent:ProtoElementInjector, index:int, bindings:List, firstBindingIsComponent:boolean = false) { + super(parent, index, bindings, firstBindingIsComponent); + } + + instantiate(parent:ElementInjector, host:ElementInjector):ElementInjector { + this.parentElementInjector = parent; + this.hostElementInjector = host; + return super.instantiate(parent, host); + } +}