feat(view): add support for components that use shadow dom emulation
This commit is contained in:
parent
df4ac0dd33
commit
da9d041f90
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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) => {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 [
|
||||
|
|
|
@ -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
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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();
|
|
@ -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();
|
|
@ -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]);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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]);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
|
@ -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', () => {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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]'
|
||||
})
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue