fix(element_injector): changed visibility rules to expose hostInjector of the component to its shadow dom
This commit is contained in:
parent
bbfb4e1dcc
commit
c51aef9f7d
@ -398,41 +398,45 @@ export class ProtoElementInjector {
|
|||||||
var bd = [];
|
var bd = [];
|
||||||
|
|
||||||
ProtoElementInjector._createDirectiveBindingData(bindings, bd, firstBindingIsComponent);
|
ProtoElementInjector._createDirectiveBindingData(bindings, bd, firstBindingIsComponent);
|
||||||
ProtoElementInjector._createHostInjectorBindingData(bindings, bd);
|
|
||||||
if (firstBindingIsComponent) {
|
if (firstBindingIsComponent) {
|
||||||
ProtoElementInjector._createViewInjectorBindingData(bindings, bd);
|
ProtoElementInjector._createViewInjectorBindingData(bindings, bd);
|
||||||
}
|
}
|
||||||
|
ProtoElementInjector._createHostInjectorBindingData(bindings, bd, firstBindingIsComponent);
|
||||||
return new ProtoElementInjector(parent, index, bd, distanceToParent, firstBindingIsComponent);
|
return new ProtoElementInjector(parent, index, bd, distanceToParent, firstBindingIsComponent);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static _createDirectiveBindingData(bindings: List<ResolvedBinding>, bd: List<BindingData>,
|
private static _createDirectiveBindingData(dirBindings: List<ResolvedBinding>,
|
||||||
|
bd: List<BindingData>,
|
||||||
firstBindingIsComponent: boolean) {
|
firstBindingIsComponent: boolean) {
|
||||||
if (firstBindingIsComponent) {
|
ListWrapper.forEach(dirBindings, dirBinding => {
|
||||||
ListWrapper.push(bd, new BindingData(bindings[0], LIGHT_DOM_AND_SHADOW_DOM));
|
ListWrapper.push(bd, ProtoElementInjector._createBindingData(
|
||||||
for (var i = 1; i < bindings.length; ++i) {
|
firstBindingIsComponent, dirBinding, dirBindings, dirBinding));
|
||||||
ListWrapper.push(bd, new BindingData(bindings[i], LIGHT_DOM));
|
});
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ListWrapper.forEach(bindings, b => {ListWrapper.push(bd, new BindingData(b, LIGHT_DOM))});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static _createHostInjectorBindingData(bindings: List<ResolvedBinding>,
|
private static _createHostInjectorBindingData(dirBindings: List<ResolvedBinding>,
|
||||||
bd: List<BindingData>) {
|
bd: List<BindingData>,
|
||||||
|
firstBindingIsComponent: boolean) {
|
||||||
var visitedIds: Map<number, boolean> = MapWrapper.create();
|
var visitedIds: Map<number, boolean> = MapWrapper.create();
|
||||||
ListWrapper.forEach(bindings, b => {
|
ListWrapper.forEach(dirBindings, dirBinding => {
|
||||||
ListWrapper.forEach(b.resolvedHostInjectables, b => {
|
ListWrapper.forEach(dirBinding.resolvedHostInjectables, b => {
|
||||||
if (MapWrapper.contains(visitedIds, b.key.id)) {
|
if (MapWrapper.contains(visitedIds, b.key.id)) {
|
||||||
throw new BaseException(
|
throw new BaseException(
|
||||||
`Multiple directives defined the same host injectable: "${stringify(b.key.token)}"`);
|
`Multiple directives defined the same host injectable: "${stringify(b.key.token)}"`);
|
||||||
}
|
}
|
||||||
MapWrapper.set(visitedIds, b.key.id, true);
|
MapWrapper.set(visitedIds, b.key.id, true);
|
||||||
ListWrapper.push(bd, new BindingData(ProtoElementInjector._createBinding(b), LIGHT_DOM));
|
ListWrapper.push(bd, ProtoElementInjector._createBindingData(
|
||||||
|
firstBindingIsComponent, dirBinding, dirBindings,
|
||||||
|
ProtoElementInjector._createBinding(b)));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static _createBindingData(firstBindingIsComponent, dirBinding, dirBindings, binding) {
|
||||||
|
var isComponent = firstBindingIsComponent && dirBindings[0] === dirBinding;
|
||||||
|
return new BindingData(binding, isComponent ? LIGHT_DOM_AND_SHADOW_DOM : LIGHT_DOM);
|
||||||
|
}
|
||||||
|
|
||||||
private static _createViewInjectorBindingData(bindings: List<ResolvedBinding>,
|
private static _createViewInjectorBindingData(bindings: List<ResolvedBinding>,
|
||||||
bd: List<BindingData>) {
|
bd: List<BindingData>) {
|
||||||
var db = <DirectiveBinding>bindings[0];
|
var db = <DirectiveBinding>bindings[0];
|
||||||
|
@ -625,15 +625,38 @@ export function main() {
|
|||||||
expect(inj.get(NeedsService).service).toEqual('service');
|
expect(inj.get(NeedsService).service).toEqual('service');
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should prioritize hostInjector over viewInjector for the same binding", () => {
|
it("should prioritize viewInjector over hostInjector for the same binding", () => {
|
||||||
var inj = injector(
|
var inj = injector(
|
||||||
ListWrapper.concat([DirectiveBinding.createFromType(NeedsService, new dirAnn.Component({
|
ListWrapper.concat([DirectiveBinding.createFromType(NeedsService, new dirAnn.Component({
|
||||||
hostInjector: [bind('service').toValue('hostService')],
|
hostInjector: [bind('service').toValue('hostService')],
|
||||||
viewInjector: [bind('service').toValue('viewService')]})
|
viewInjector: [bind('service').toValue('viewService')]})
|
||||||
)], extraBindings), null, true);
|
)], extraBindings), null, true);
|
||||||
expect(inj.get(NeedsService).service).toEqual('hostService');
|
expect(inj.get(NeedsService).service).toEqual('viewService');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should instantiate a directive in a view that depends on hostInjector bindings of the component", () => {
|
||||||
|
var shadowInj = hostShadowInjectors(
|
||||||
|
ListWrapper.concat([DirectiveBinding.createFromType(SimpleDirective, new dirAnn.Component({
|
||||||
|
hostInjector: [bind('service').toValue('hostService')]})
|
||||||
|
)], extraBindings),
|
||||||
|
ListWrapper.concat([NeedsService], extraBindings)
|
||||||
|
);
|
||||||
|
expect(shadowInj.get(NeedsService).service).toEqual('hostService');
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should not instantiate a directive in a view that depends on hostInjector bindings of a decorator directive", () => {
|
||||||
|
expect(() => {
|
||||||
|
hostShadowInjectors(
|
||||||
|
ListWrapper.concat([
|
||||||
|
SimpleDirective,
|
||||||
|
DirectiveBinding.createFromType(SomeOtherDirective, new dirAnn.Directive({
|
||||||
|
hostInjector: [bind('service').toValue('hostService')]})
|
||||||
|
)], extraBindings),
|
||||||
|
|
||||||
|
ListWrapper.concat([NeedsService], extraBindings)
|
||||||
|
);
|
||||||
|
}).toThrowError(new RegExp("No provider for service!"));
|
||||||
|
});
|
||||||
|
|
||||||
it("should instantiate directives that depend on app services", () => {
|
it("should instantiate directives that depend on app services", () => {
|
||||||
var appInjector = Injector.resolveAndCreate(
|
var appInjector = Injector.resolveAndCreate(
|
||||||
|
@ -973,28 +973,6 @@ export function main() {
|
|||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
||||||
it('should prioritze hostInjector over viewInjector for the same binding',
|
|
||||||
inject([TestBed, AsyncTestCompleter], (tb: TestBed, async) => {
|
|
||||||
tb.overrideView(MyComp, new viewAnn.View({
|
|
||||||
template: `
|
|
||||||
<directive-providing-injectable>
|
|
||||||
<directive-consuming-injectable #consuming>
|
|
||||||
</directive-consuming-injectable>
|
|
||||||
</directive-providing-injectable>
|
|
||||||
`,
|
|
||||||
directives:
|
|
||||||
[DirectiveProvidingInjectableInHostAndView, DirectiveConsumingInjectable]
|
|
||||||
}));
|
|
||||||
tb.createView(MyComp, {context: ctx})
|
|
||||||
.then((view) => {
|
|
||||||
var comp = view.rawView.locals.get("consuming");
|
|
||||||
expect(comp.injectable).toEqual("host");
|
|
||||||
|
|
||||||
async.done();
|
|
||||||
});
|
|
||||||
}));
|
|
||||||
|
|
||||||
it("should support viewInjector",
|
it("should support viewInjector",
|
||||||
inject([TestBed, AsyncTestCompleter], (tb: TestBed, async) => {
|
inject([TestBed, AsyncTestCompleter], (tb: TestBed, async) => {
|
||||||
tb.overrideView(DirectiveProvidingInjectableInView, new viewAnn.View({
|
tb.overrideView(DirectiveProvidingInjectableInView, new viewAnn.View({
|
||||||
@ -1688,23 +1666,15 @@ class GrandParentProvidingEventBus {
|
|||||||
constructor(bus: EventBus) { this.bus = bus; }
|
constructor(bus: EventBus) { this.bus = bus; }
|
||||||
}
|
}
|
||||||
|
|
||||||
function createParentBusHost(peb) {
|
function createParentBus(peb) {
|
||||||
return new EventBus(peb, "parent");
|
return new EventBus(peb, "parent");
|
||||||
}
|
}
|
||||||
|
|
||||||
function createParentBusView(p) {
|
|
||||||
return p.bus;
|
|
||||||
}
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'parent-providing-event-bus',
|
selector: 'parent-providing-event-bus',
|
||||||
hostInjector: [
|
hostInjector: [
|
||||||
new Binding(EventBus,
|
new Binding(EventBus,
|
||||||
{toFactory: createParentBusHost, deps: [[EventBus, new visAnn.Unbounded()]]})
|
{toFactory: createParentBus, deps: [[EventBus, new visAnn.Unbounded()]]})
|
||||||
],
|
|
||||||
viewInjector: [
|
|
||||||
new Binding(
|
|
||||||
EventBus,
|
|
||||||
{toFactory: createParentBusView, deps: [[forwardRef(() => ParentProvidingEventBus)]]})
|
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
@View({
|
@View({
|
||||||
@ -1718,7 +1688,6 @@ class ParentProvidingEventBus {
|
|||||||
grandParentBus: EventBus;
|
grandParentBus: EventBus;
|
||||||
|
|
||||||
constructor(bus: EventBus, @Unbounded() grandParentBus: EventBus) {
|
constructor(bus: EventBus, @Unbounded() grandParentBus: EventBus) {
|
||||||
// constructor(bus: EventBus) {
|
|
||||||
this.bus = bus;
|
this.bus = bus;
|
||||||
this.grandParentBus = grandParentBus;
|
this.grandParentBus = grandParentBus;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user