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

@ -1,7 +1,7 @@
import {DOM, document} from 'facade/dom';
import {isBlank, Type} from 'facade/lang';
import {MapWrapper} from 'facade/collection';
import {AnnotatedType} from 'core/compiler/annotated_type';
import {DirectiveMetadata} from 'core/compiler/directive_metadata';
import {Parser} from 'change_detection/parser/parser';
import {Lexer} from 'change_detection/parser/lexer';
@ -81,7 +81,7 @@ export function main() {
var reader = new DirectiveMetadataReader();
var cache = new CompilerCache();
var compiler = new Compiler(null, reader, new Parser(new Lexer()), cache);
var annotatedComponent = reader.annotatedType(BenchmarkComponent);
var annotatedComponent = reader.read(BenchmarkComponent);
var templateNoBindings = loadTemplate('templateNoBindings', COUNT);
var templateWithBindings = loadTemplate('templateWithBindings', COUNT);

View File

@ -1,6 +1,7 @@
import {ABSTRACT, CONST, normalizeBlank} from 'facade/lang';
import {List} from 'facade/collection';
import {TemplateConfig} from './template_config';
import {ShadowDomStrategy} from '../compiler/shadow_dom';
@ABSTRACT()
@ -35,6 +36,7 @@ export class Component extends Directive {
lightDomServices:any; //List;
shadowDomServices:any; //List;
componentServices:any; //List;
shadowDom:any; //ShadowDomStrategy;
@CONST()
constructor({
@ -44,7 +46,8 @@ export class Component extends Directive {
lightDomServices,
shadowDomServices,
componentServices,
implementsTypes
implementsTypes,
shadowDom
}:{
selector:String,
bind:Object,
@ -52,7 +55,8 @@ export class Component extends Directive {
lightDomServices:List,
shadowDomServices:List,
componentServices:List,
implementsTypes:List
implementsTypes:List,
shadowDom:ShadowDomStrategy
}={})
{
super({
@ -65,6 +69,7 @@ export class Component extends Directive {
this.lightDomServices = lightDomServices;
this.shadowDomServices = shadowDomServices;
this.componentServices = componentServices;
this.shadowDom = shadowDom;
}
}

View File

@ -10,7 +10,7 @@ import {ChangeDetector} from 'change_detection/change_detector';
import {RecordRange} from 'change_detection/record_range';
import {TemplateLoader} from './compiler/template_loader';
import {DirectiveMetadataReader} from './compiler/directive_metadata_reader';
import {AnnotatedType} from './compiler/annotated_type';
import {DirectiveMetadata} from './compiler/directive_metadata';
import {List, ListWrapper} from 'facade/collection';
import {PromiseWrapper} from 'facade/async';
import {VmTurnZone} from 'core/zone/vm_turn_zone';
@ -36,7 +36,7 @@ export function documentDependentBindings(appComponentType) {
// TODO(rado): inspect annotation here and warn if there are bindings,
// lightDomServices, and other component annotations that are skipped
// for bootstrapping components.
return reader.annotatedType(appComponentType);
return reader.read(appComponentType);
}, [DirectiveMetadataReader]),
bind(appElementToken).toFactory((appComponentAnnotatedType, appDocument) => {

View File

@ -11,7 +11,7 @@ import {CompilePipeline} from './pipeline/compile_pipeline';
import {CompileElement} from './pipeline/compile_element';
import {createDefaultSteps} from './pipeline/default_steps';
import {TemplateLoader} from './template_loader';
import {AnnotatedType} from './annotated_type';
import {DirectiveMetadata} from './directive_metadata';
import {Component} from '../annotations/annotations';
/**
@ -59,12 +59,12 @@ export class Compiler {
this._compilerCache = cache;
}
createSteps(component:AnnotatedType):List<CompileStep> {
createSteps(component:DirectiveMetadata):List<CompileStep> {
var annotation: Component = component.annotation;
var directives = annotation.template.directives;
var annotatedDirectives = ListWrapper.create();
for (var i=0; i<directives.length; i++) {
ListWrapper.push(annotatedDirectives, this._reader.annotatedType(directives[i]));
ListWrapper.push(annotatedDirectives, this._reader.read(directives[i]));
}
return createDefaultSteps(this._parser, component, annotatedDirectives);
}
@ -75,12 +75,12 @@ export class Compiler {
// transitively via the _templateLoader and store them in templateCache
return PromiseWrapper.resolve(this.compileAllLoaded(
templateCache, this._reader.annotatedType(component), templateRoot)
templateCache, this._reader.read(component), templateRoot)
);
}
// public so that we can compile in sync in performance tests.
compileAllLoaded(templateCache, component:AnnotatedType, templateRoot:Element = null):ProtoView {
compileAllLoaded(templateCache, component:DirectiveMetadata, templateRoot:Element = null):ProtoView {
var rootProtoView = this._compilerCache.get(component.type);
if (isPresent(rootProtoView)) {
return rootProtoView;

View File

@ -1,14 +1,18 @@
import {Type, FIELD} from 'facade/lang';
import {Directive} from '../annotations/annotations'
import {ShadowDomStrategy} from './shadow_dom';
/**
* Combination of a type with the Directive annotation
*/
export class AnnotatedType {
export class DirectiveMetadata {
type:Type;
annotation:Directive;
constructor(type:Type, annotation:Directive) {
shadowDomStrategy:ShadowDomStrategy;
constructor(type:Type, annotation:Directive, shadowDomStrategy:ShadowDomStrategy) {
this.annotation = annotation;
this.type = type;
this.shadowDomStrategy = shadowDomStrategy;
}
}

View File

@ -1,27 +1,29 @@
import {Type, isPresent, BaseException, stringify} from 'facade/lang';
import {Directive} from '../annotations/annotations';
import {AnnotatedType} from './annotated_type';
import {Directive, Component} from '../annotations/annotations';
import {DirectiveMetadata} from './directive_metadata';
import {reflector} from 'reflection/reflection';
import {ShadowDom, ShadowDomStrategy, ShadowDomNative} from './shadow_dom';
/**
* Interface representing a way of extracting [Directive] annotations from
* [Type]. This interface has three native implementations:
*
* 1) JavaScript native implementation
* 2) Dart reflective implementation
* 3) Dart transformer generated implementation
*/
export class DirectiveMetadataReader {
annotatedType(type:Type):AnnotatedType {
read(type:Type):DirectiveMetadata {
var annotations = reflector.annotations(type);
if (isPresent(annotations)) {
for (var i=0; i<annotations.length; i++) {
var annotation = annotations[i];
if (annotation instanceof Component) {
return new DirectiveMetadata(type, annotation, this.parseShadowDomStrategy(annotation));
}
if (annotation instanceof Directive) {
return new AnnotatedType(type, annotation);
return new DirectiveMetadata(type, annotation, null);
}
}
}
throw new BaseException(`No Directive annotation found on ${stringify(type)}`);
}
parseShadowDomStrategy(annotation:Component):ShadowDomStrategy{
return isPresent(annotation.shadowDom) ? annotation.shadowDom : ShadowDomNative;
}
}

View File

@ -1,20 +1,20 @@
import {ProtoElementInjector} from './element_injector';
import {FIELD} from 'facade/lang';
import {MapWrapper} from 'facade/collection';
import {AnnotatedType} from './annotated_type';
import {DirectiveMetadata} from './directive_metadata';
import {List, Map} from 'facade/collection';
import {ProtoView} from './view';
export class ElementBinder {
protoElementInjector:ProtoElementInjector;
componentDirective:AnnotatedType;
templateDirective:AnnotatedType;
componentDirective:DirectiveMetadata;
templateDirective:DirectiveMetadata;
textNodeIndices:List<int>;
hasElementPropertyBindings:boolean;
nestedProtoView: ProtoView;
events:Map;
constructor(
protoElementInjector: ProtoElementInjector, componentDirective:AnnotatedType, templateDirective:AnnotatedType) {
protoElementInjector: ProtoElementInjector, componentDirective:DirectiveMetadata, templateDirective:DirectiveMetadata) {
this.protoElementInjector = protoElementInjector;
this.componentDirective = componentDirective;
this.templateDirective = templateDirective;

View File

@ -1,7 +1,7 @@
import {List, Map, ListWrapper, MapWrapper} from 'facade/collection';
import {Element, DOM} from 'facade/dom';
import {int, isBlank, isPresent} from 'facade/lang';
import {AnnotatedType} from '../annotated_type';
import {DirectiveMetadata} from '../directive_metadata';
import {Decorator} from '../../annotations/annotations';
import {Component} from '../../annotations/annotations';
import {Template} from '../../annotations/annotations';
@ -24,9 +24,9 @@ export class CompileElement {
propertyBindings:Map;
eventBindings:Map;
variableBindings:Map;
decoratorDirectives:List<AnnotatedType>;
templateDirective:AnnotatedType;
componentDirective:AnnotatedType;
decoratorDirectives:List<DirectiveMetadata>;
templateDirective:DirectiveMetadata;
componentDirective:DirectiveMetadata;
isViewRoot:boolean;
hasBindings:boolean;
inheritedProtoView:ProtoView;
@ -110,7 +110,7 @@ export class CompileElement {
MapWrapper.set(this.eventBindings, eventName, expression);
}
addDirective(directive:AnnotatedType) {
addDirective(directive:DirectiveMetadata) {
var annotation = directive.annotation;
if (annotation instanceof Decorator) {
if (isBlank(this.decoratorDirectives)) {

View File

@ -4,7 +4,7 @@ import {Element, Node, DOM} from 'facade/dom';
import {CompileElement} from './compile_element';
import {CompileControl} from './compile_control';
import {CompileStep} from './compile_step';
import {AnnotatedType} from '../annotated_type';
import {DirectiveMetadata} from '../directive_metadata';
/**
* CompilePipeline for executing CompileSteps recursively for

View File

@ -1,6 +1,6 @@
import {CompileElement} from './compile_element';
import {CompileControl} from './compile_control';
import {AnnotatedType} from '../annotated_type';
import {DirectiveMetadata} from '../directive_metadata';
/**
* One part of the compile process.

View File

@ -9,7 +9,7 @@ import {ElementBindingMarker} from './element_binding_marker';
import {ProtoViewBuilder} from './proto_view_builder';
import {ProtoElementInjectorBuilder} from './proto_element_injector_builder';
import {ElementBinderBuilder} from './element_binder_builder';
import {AnnotatedType} from 'core/compiler/annotated_type';
import {DirectiveMetadata} from 'core/compiler/directive_metadata';
import {stringify} from 'facade/lang';
/**
@ -17,8 +17,8 @@ import {stringify} from 'facade/lang';
* Takes in an HTMLElement and produces the ProtoViews,
* ProtoElementInjectors and ElementBinders in the end.
*/
export function createDefaultSteps(parser:Parser, compiledComponent: AnnotatedType,
directives: List<AnnotatedType>) {
export function createDefaultSteps(parser:Parser, compiledComponent: DirectiveMetadata,
directives: List<DirectiveMetadata>) {
var compilationUnit = stringify(compiledComponent.type);
return [

View File

@ -4,7 +4,7 @@ import {TemplateElement} from 'facade/dom';
import {SelectorMatcher} from '../selector';
import {CssSelector} from '../selector';
import {AnnotatedType} from '../annotated_type';
import {DirectiveMetadata} from '../directive_metadata';
import {Template} from '../../annotations/annotations';
import {Component} from '../../annotations/annotations';
import {CompileStep} from './compile_step';
@ -28,13 +28,13 @@ import {CompileControl} from './compile_control';
*/
export class DirectiveParser extends CompileStep {
_selectorMatcher:SelectorMatcher;
constructor(directives:List<AnnotatedType>) {
constructor(directives:List<DirectiveMetadata>) {
this._selectorMatcher = new SelectorMatcher();
for (var i=0; i<directives.length; i++) {
var annotatedType = directives[i];
var directiveMetadata = directives[i];
this._selectorMatcher.addSelectable(
CssSelector.parse(annotatedType.annotation.selector),
annotatedType
CssSelector.parse(directiveMetadata.annotation.selector),
directiveMetadata
);
}
}

View File

@ -8,7 +8,7 @@ import {Parser} from 'change_detection/parser/parser';
import {ProtoRecordRange} from 'change_detection/record_range';
import {Component, Directive} from '../../annotations/annotations';
import {AnnotatedType} from '../annotated_type';
import {DirectiveMetadata} from '../directive_metadata';
import {ProtoView, ElementPropertyMemento, DirectivePropertyMemento} from '../view';
import {ProtoElementInjector} from '../element_injector';
import {ElementBinder} from '../element_binder';

View File

@ -0,0 +1,9 @@
library angular.core.compiler.shadow_dom;
//TODO: merge this file with shadow_dom.es6 when the traspiler support creating const globals
import './shadow_dom_strategy.dart';
export './shadow_dom_strategy.dart';
const ShadowDomEmulated = const EmulatedShadowDomStrategy();
const ShadowDomNative = const NativeShadowDomStrategy();

View File

@ -0,0 +1,5 @@
import {EmulatedShadowDomStrategy, NativeShadowDomStrategy} from './shadow_dom_strategy';
export * from './shadow_dom_strategy';
export var ShadowDomEmulated = new EmulatedShadowDomStrategy();
export var ShadowDomNative = new NativeShadowDomStrategy();

View File

@ -0,0 +1,30 @@
import {CONST} from 'facade/lang';
import {DOM} from 'facade/dom';
import {Element} from 'facade/dom';
import {View} from './view';
export class ShadowDomStrategy {
@CONST() constructor() {}
attachTemplate(el:Element, view:View){}
}
export class EmulatedShadowDomStrategy extends ShadowDomStrategy {
@CONST() constructor() {}
attachTemplate(el:Element, view:View){
DOM.clearNodes(el);
moveViewNodesIntoParent(el, view);
}
}
export class NativeShadowDomStrategy extends ShadowDomStrategy {
@CONST() constructor() {}
attachTemplate(el:Element, view:View){
moveViewNodesIntoParent(el.createShadowRoot(), view);
}
}
function moveViewNodesIntoParent(parent, view) {
for (var i = 0; i < view.nodes.length; ++i) {
DOM.appendChild(parent, view.nodes[i]);
}
}

View File

@ -6,7 +6,7 @@ import {AST} from 'change_detection/parser/ast';
import {ProtoElementInjector, ElementInjector, PreBuiltObjects} from './element_injector';
import {ElementBinder} from './element_binder';
import {AnnotatedType} from './annotated_type';
import {DirectiveMetadata} from './directive_metadata';
import {SetterFn} from 'reflection/types';
import {FIELD, IMPLEMENTS, int, isPresent, isBlank, BaseException} from 'facade/lang';
import {Injector} from 'di/di';
@ -350,7 +350,8 @@ export class ProtoView {
if (isPresent(binder.componentDirective)) {
var childView = binder.nestedProtoView.instantiate(elementInjector);
view.recordRange.addRange(childView.recordRange);
ViewPort.moveViewNodesIntoParent(element.createShadowRoot(), childView);
binder.componentDirective.shadowDomStrategy.attachTemplate(element, childView);
ListWrapper.push(componentChildViews, childView);
}
}
@ -367,7 +368,7 @@ export class ProtoView {
}
bindElement(protoElementInjector:ProtoElementInjector,
componentDirective:AnnotatedType = null, templateDirective:AnnotatedType = null):ElementBinder {
componentDirective:DirectiveMetadata = null, templateDirective:DirectiveMetadata = null):ElementBinder {
var elBinder = new ElementBinder(protoElementInjector, componentDirective, templateDirective);
ListWrapper.push(this.elementBinders, elBinder);
return elBinder;
@ -434,7 +435,7 @@ export class ProtoView {
// and the component template is already compiled into protoView.
// Used for bootstrapping.
static createRootProtoView(protoView: ProtoView,
insertionElement, rootComponentAnnotatedType: AnnotatedType): ProtoView {
insertionElement, rootComponentAnnotatedType: DirectiveMetadata): ProtoView {
DOM.addClass(insertionElement, 'ng-binding');
var rootProtoView = new ProtoView(insertionElement, new ProtoRecordRange());
rootProtoView.instantiateInPlace = true;

View File

@ -105,12 +105,6 @@ export class ViewPort {
}
}
static moveViewNodesIntoParent(parent, view) {
for (var i = 0; i < view.nodes.length; ++i) {
DOM.appendChild(parent, view.nodes[i]);
}
}
static moveViewNodesAfterSibling(sibling, view) {
for (var i = view.nodes.length - 1; i >= 0; --i) {
DOM.insertAfter(sibling, view.nodes[i]);

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]'
})

View File

@ -47,6 +47,9 @@ class DOM {
static List<Node> childNodes(el) {
return el.childNodes;
}
static clearNodes(el) {
el.nodes = [];
}
static appendChild(el, node) {
el.append(node);
}

View File

@ -40,6 +40,9 @@ export class DOM {
static childNodes(el):NodeList {
return el.childNodes;
}
static clearNodes(el) {
el.innerHTML = "";
}
static appendChild(el, node) {
el.appendChild(node);
}