feat(view): add support for components that use shadow dom emulation

This commit is contained in:
vsavkin
2014-12-23 10:45:20 -08:00
parent df4ac0dd33
commit da9d041f90
27 changed files with 188 additions and 89 deletions

View File

@ -66,7 +66,7 @@ export function main() {
current.inheritedProtoView = new ProtoView(current.element, null);
current.inheritedElementBinder = current.inheritedProtoView.bindElement(null);
if (current.element === mainEl) {
current.componentDirective = reader.annotatedType(NestedComponent);
current.componentDirective = reader.read(NestedComponent);
}
});
compiler.compile(MainComponent, mainEl).then( (protoView) => {
@ -97,7 +97,7 @@ export function main() {
var compiler = createCompiler( (parent, current, control) => {
current.inheritedProtoView = new ProtoView(current.element, null);
current.inheritedElementBinder = current.inheritedProtoView.bindElement(null);
current.componentDirective = reader.annotatedType(RecursiveComponent);
current.componentDirective = reader.read(RecursiveComponent);
});
compiler.compile(RecursiveComponent, null).then( (protoView) => {
expect(protoView.elementBinders[0].nestedProtoView).toBe(protoView);

View File

@ -1,7 +1,8 @@
import {ddescribe, describe, it, iit, expect, beforeEach} from 'test_lib/test_lib';
import {DirectiveMetadataReader} from 'core/compiler/directive_metadata_reader';
import {Decorator} from 'core/annotations/annotations';
import {AnnotatedType} from 'core/compiler/annotated_type';
import {Decorator, Component} from 'core/annotations/annotations';
import {DirectiveMetadata} from 'core/compiler/directive_metadata';
import {ShadowDomEmulated, ShadowDomNative} from 'core/compiler/shadow_dom';
@Decorator({
selector: 'someSelector'
@ -9,28 +10,50 @@ import {AnnotatedType} from 'core/compiler/annotated_type';
class SomeDirective {
}
@Component({
selector: 'someSelector'
})
class ComponentWithoutExplicitShadowDomStrategy {}
@Component({
selector: 'someSelector',
shadowDom: ShadowDomEmulated
})
class ComponentWithExplicitShadowDomStrategy {}
class SomeDirectiveWithoutAnnotation {
}
export function main() {
describe("DirectiveMetadataReader", () => {
var rader;
var reader;
beforeEach( () => {
rader = new DirectiveMetadataReader();
reader = new DirectiveMetadataReader();
});
it('should read out the annotation', () => {
var annoatedDirective = rader.annotatedType(SomeDirective);
expect(annoatedDirective).toEqual(
new AnnotatedType(SomeDirective, new Decorator({selector: 'someSelector'})));
var directiveMetadata = reader.read(SomeDirective);
expect(directiveMetadata).toEqual(
new DirectiveMetadata(SomeDirective, new Decorator({selector: 'someSelector'}), null));
});
it('should throw if not matching annotation is found', () => {
expect(() => {
rader.annotatedType(SomeDirectiveWithoutAnnotation);
reader.read(SomeDirectiveWithoutAnnotation);
}).toThrowError('No Directive annotation found on SomeDirectiveWithoutAnnotation');
});
describe("shadow dom strategy", () => {
it('should return the provided shadow dom strategy when it is present', () => {
var directiveMetadata = reader.read(ComponentWithExplicitShadowDomStrategy);
expect(directiveMetadata.shadowDomStrategy).toEqual(ShadowDomEmulated);
});
it('should return Native otherwise', () => {
var directiveMetadata = reader.read(ComponentWithoutExplicitShadowDomStrategy);
expect(directiveMetadata.shadowDomStrategy).toEqual(ShadowDomNative);
});
});
});
}

View File

@ -28,7 +28,7 @@ export function main() {
var parser = new Parser(new Lexer());
var annotatedDirectives = ListWrapper.create();
for (var i=0; i<directives.length; i++) {
ListWrapper.push(annotatedDirectives, reader.annotatedType(directives[i]));
ListWrapper.push(annotatedDirectives, reader.read(directives[i]));
}
return new CompilePipeline([new MockStep((parent, current, control) => {
@ -53,7 +53,7 @@ export function main() {
describe('component directives', () => {
it('should detect them in attributes', () => {
var results = createPipeline().process(createElement('<div some-comp></div>'));
expect(results[0].componentDirective).toEqual(reader.annotatedType(SomeComponent));
expect(results[0].componentDirective).toEqual(reader.read(SomeComponent));
});
it('should detect them in property bindings', () => {
@ -61,7 +61,7 @@ export function main() {
'some-comp': 'someExpr'
}});
var results = pipeline.process(createElement('<div></div>'));
expect(results[0].componentDirective).toEqual(reader.annotatedType(SomeComponent));
expect(results[0].componentDirective).toEqual(reader.read(SomeComponent));
});
it('should detect them in variable bindings', () => {
@ -69,7 +69,7 @@ export function main() {
'some-comp': 'someExpr'
}});
var results = pipeline.process(createElement('<div></div>'));
expect(results[0].componentDirective).toEqual(reader.annotatedType(SomeComponent));
expect(results[0].componentDirective).toEqual(reader.read(SomeComponent));
});
it('should not allow multiple component directives on the same element', () => {
@ -92,7 +92,7 @@ export function main() {
describe('template directives', () => {
it('should detect them in attributes', () => {
var results = createPipeline().process(createElement('<template some-templ></template>'));
expect(results[0].templateDirective).toEqual(reader.annotatedType(SomeTemplate));
expect(results[0].templateDirective).toEqual(reader.read(SomeTemplate));
});
it('should detect them in property bindings', () => {
@ -100,7 +100,7 @@ export function main() {
'some-templ': 'someExpr'
}});
var results = pipeline.process(createElement('<template></template>'));
expect(results[0].templateDirective).toEqual(reader.annotatedType(SomeTemplate));
expect(results[0].templateDirective).toEqual(reader.read(SomeTemplate));
});
it('should detect them in variable bindings', () => {
@ -108,7 +108,7 @@ export function main() {
'some-templ': 'someExpr'
}});
var results = pipeline.process(createElement('<template></template>'));
expect(results[0].templateDirective).toEqual(reader.annotatedType(SomeTemplate));
expect(results[0].templateDirective).toEqual(reader.read(SomeTemplate));
});
it('should not allow multiple template directives on the same element', () => {
@ -131,7 +131,7 @@ export function main() {
describe('decorator directives', () => {
it('should detect them in attributes', () => {
var results = createPipeline().process(createElement('<div some-decor></div>'));
expect(results[0].decoratorDirectives).toEqual([reader.annotatedType(SomeDecorator)]);
expect(results[0].decoratorDirectives).toEqual([reader.read(SomeDecorator)]);
});
it('should detect them in property bindings', () => {
@ -139,7 +139,7 @@ export function main() {
'some-decor': 'someExpr'
}});
var results = pipeline.process(createElement('<div></div>'));
expect(results[0].decoratorDirectives).toEqual([reader.annotatedType(SomeDecorator)]);
expect(results[0].decoratorDirectives).toEqual([reader.read(SomeDecorator)]);
});
it('should detect them in variable bindings', () => {
@ -147,7 +147,7 @@ export function main() {
'some-decor': 'someExpr'
}});
var results = pipeline.process(createElement('<div></div>'));
expect(results[0].decoratorDirectives).toEqual([reader.annotatedType(SomeDecorator)]);
expect(results[0].decoratorDirectives).toEqual([reader.read(SomeDecorator)]);
});
it('should not allow decorator directives on <template> elements', () => {

View File

@ -59,7 +59,7 @@ export function main() {
if (isPresent(current.element.getAttribute('directives'))) {
hasBinding = true;
for (var i=0; i<directives.length; i++) {
current.addDirective(reflector.annotatedType(directives[i]));
current.addDirective(reflector.read(directives[i]));
}
}
if (hasBinding) {

View File

@ -32,7 +32,7 @@ export function main() {
}
if (isPresent(directives)) {
for (var i=0; i<directives.length; i++) {
current.addDirective(reader.annotatedType(directives[i]));
current.addDirective(reader.read(directives[i]));
}
}
}), new ElementBindingMarker()

View File

@ -32,7 +32,7 @@ export function main() {
}
if (isPresent(current.element.getAttribute('directives'))) {
for (var i=0; i<directives.length; i++) {
current.addDirective(reader.annotatedType(directives[i]));
current.addDirective(reader.read(directives[i]));
}
}
current.inheritedProtoView = protoView;

View File

@ -1,6 +1,7 @@
import {describe, xit, it, expect, beforeEach, ddescribe, iit} from 'test_lib/test_lib';
import {ProtoView, ElementPropertyMemento, DirectivePropertyMemento} from 'core/compiler/view';
import {ProtoElementInjector, ElementInjector} from 'core/compiler/element_injector';
import {ShadowDomEmulated} from 'core/compiler/shadow_dom';
import {DirectiveMetadataReader} from 'core/compiler/directive_metadata_reader';
import {Component, Decorator, Template} from 'core/annotations/annotations';
import {OnChange} from 'core/core';
@ -29,8 +30,8 @@ export function main() {
beforeEach(() => {
parser = new Parser(new Lexer());
someComponentDirective = new DirectiveMetadataReader().annotatedType(SomeComponent);
someTemplateDirective = new DirectiveMetadataReader().annotatedType(SomeTemplate);
someComponentDirective = new DirectiveMetadataReader().read(SomeComponent);
someTemplateDirective = new DirectiveMetadataReader().read(SomeTemplate);
});
describe('instatiated from protoView', () => {
@ -258,15 +259,6 @@ export function main() {
return view;
}
it('should create shadow dom', () => {
var subpv = new ProtoView(createElement('<span>hello shadow dom</span>'), new ProtoRecordRange());
var pv = createComponentWithSubPV(subpv);
var view = createNestedView(pv);
expect(view.nodes[0].shadowRoot.childNodes[0].childNodes[0].nodeValue).toEqual('hello shadow dom');
});
it('should expose component services to the component', () => {
var subpv = new ProtoView(createElement('<span></span>'), new ProtoRecordRange());
var pv = createComponentWithSubPV(subpv);
@ -316,6 +308,28 @@ export function main() {
view.componentChildViews.forEach(
(view) => expectViewHasNoDirectiveInstances(view));
});
it('should create shadow dom', () => {
var subpv = new ProtoView(createElement('<span>hello shadow dom</span>'), new ProtoRecordRange());
var pv = createComponentWithSubPV(subpv);
var view = createNestedView(pv);
expect(view.nodes[0].shadowRoot.childNodes[0].childNodes[0].nodeValue).toEqual('hello shadow dom');
});
it('should use the provided shadow DOM strategy', () => {
var subpv = new ProtoView(createElement('<span>hello shadow dom</span>'), new ProtoRecordRange());
var pv = new ProtoView(createElement('<cmp class="ng-binding"></cmp>'), new ProtoRecordRange());
var binder = pv.bindElement(new ProtoElementInjector(null, 0, [SomeComponentWithEmulatedShadowDom], true));
binder.componentDirective = new DirectiveMetadataReader().read(SomeComponentWithEmulatedShadowDom);
binder.nestedProtoView = subpv;
var view = createNestedView(pv);
expect(view.nodes[0].childNodes[0].childNodes[0].nodeValue).toEqual('hello shadow dom');
});
});
describe('with template views', () => {
@ -485,6 +499,12 @@ class SomeComponent {
}
}
@Component({
shadowDom: ShadowDomEmulated
})
class SomeComponentWithEmulatedShadowDom {
}
@Decorator({
selector: '[dec]'
})