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 {DOM, document} from 'facade/dom';
|
||||||
import {isBlank, Type} from 'facade/lang';
|
import {isBlank, Type} from 'facade/lang';
|
||||||
import {MapWrapper} from 'facade/collection';
|
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 {Parser} from 'change_detection/parser/parser';
|
||||||
import {Lexer} from 'change_detection/parser/lexer';
|
import {Lexer} from 'change_detection/parser/lexer';
|
||||||
@ -81,7 +81,7 @@ export function main() {
|
|||||||
var reader = new DirectiveMetadataReader();
|
var reader = new DirectiveMetadataReader();
|
||||||
var cache = new CompilerCache();
|
var cache = new CompilerCache();
|
||||||
var compiler = new Compiler(null, reader, new Parser(new Lexer()), cache);
|
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 templateNoBindings = loadTemplate('templateNoBindings', COUNT);
|
||||||
var templateWithBindings = loadTemplate('templateWithBindings', COUNT);
|
var templateWithBindings = loadTemplate('templateWithBindings', COUNT);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import {ABSTRACT, CONST, normalizeBlank} from 'facade/lang';
|
import {ABSTRACT, CONST, normalizeBlank} from 'facade/lang';
|
||||||
import {List} from 'facade/collection';
|
import {List} from 'facade/collection';
|
||||||
import {TemplateConfig} from './template_config';
|
import {TemplateConfig} from './template_config';
|
||||||
|
import {ShadowDomStrategy} from '../compiler/shadow_dom';
|
||||||
|
|
||||||
|
|
||||||
@ABSTRACT()
|
@ABSTRACT()
|
||||||
@ -35,6 +36,7 @@ export class Component extends Directive {
|
|||||||
lightDomServices:any; //List;
|
lightDomServices:any; //List;
|
||||||
shadowDomServices:any; //List;
|
shadowDomServices:any; //List;
|
||||||
componentServices:any; //List;
|
componentServices:any; //List;
|
||||||
|
shadowDom:any; //ShadowDomStrategy;
|
||||||
|
|
||||||
@CONST()
|
@CONST()
|
||||||
constructor({
|
constructor({
|
||||||
@ -44,7 +46,8 @@ export class Component extends Directive {
|
|||||||
lightDomServices,
|
lightDomServices,
|
||||||
shadowDomServices,
|
shadowDomServices,
|
||||||
componentServices,
|
componentServices,
|
||||||
implementsTypes
|
implementsTypes,
|
||||||
|
shadowDom
|
||||||
}:{
|
}:{
|
||||||
selector:String,
|
selector:String,
|
||||||
bind:Object,
|
bind:Object,
|
||||||
@ -52,7 +55,8 @@ export class Component extends Directive {
|
|||||||
lightDomServices:List,
|
lightDomServices:List,
|
||||||
shadowDomServices:List,
|
shadowDomServices:List,
|
||||||
componentServices:List,
|
componentServices:List,
|
||||||
implementsTypes:List
|
implementsTypes:List,
|
||||||
|
shadowDom:ShadowDomStrategy
|
||||||
}={})
|
}={})
|
||||||
{
|
{
|
||||||
super({
|
super({
|
||||||
@ -65,6 +69,7 @@ export class Component extends Directive {
|
|||||||
this.lightDomServices = lightDomServices;
|
this.lightDomServices = lightDomServices;
|
||||||
this.shadowDomServices = shadowDomServices;
|
this.shadowDomServices = shadowDomServices;
|
||||||
this.componentServices = componentServices;
|
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 {RecordRange} from 'change_detection/record_range';
|
||||||
import {TemplateLoader} from './compiler/template_loader';
|
import {TemplateLoader} from './compiler/template_loader';
|
||||||
import {DirectiveMetadataReader} from './compiler/directive_metadata_reader';
|
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 {List, ListWrapper} from 'facade/collection';
|
||||||
import {PromiseWrapper} from 'facade/async';
|
import {PromiseWrapper} from 'facade/async';
|
||||||
import {VmTurnZone} from 'core/zone/vm_turn_zone';
|
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,
|
// TODO(rado): inspect annotation here and warn if there are bindings,
|
||||||
// lightDomServices, and other component annotations that are skipped
|
// lightDomServices, and other component annotations that are skipped
|
||||||
// for bootstrapping components.
|
// for bootstrapping components.
|
||||||
return reader.annotatedType(appComponentType);
|
return reader.read(appComponentType);
|
||||||
}, [DirectiveMetadataReader]),
|
}, [DirectiveMetadataReader]),
|
||||||
|
|
||||||
bind(appElementToken).toFactory((appComponentAnnotatedType, appDocument) => {
|
bind(appElementToken).toFactory((appComponentAnnotatedType, appDocument) => {
|
||||||
|
@ -11,7 +11,7 @@ import {CompilePipeline} from './pipeline/compile_pipeline';
|
|||||||
import {CompileElement} from './pipeline/compile_element';
|
import {CompileElement} from './pipeline/compile_element';
|
||||||
import {createDefaultSteps} from './pipeline/default_steps';
|
import {createDefaultSteps} from './pipeline/default_steps';
|
||||||
import {TemplateLoader} from './template_loader';
|
import {TemplateLoader} from './template_loader';
|
||||||
import {AnnotatedType} from './annotated_type';
|
import {DirectiveMetadata} from './directive_metadata';
|
||||||
import {Component} from '../annotations/annotations';
|
import {Component} from '../annotations/annotations';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -59,12 +59,12 @@ export class Compiler {
|
|||||||
this._compilerCache = cache;
|
this._compilerCache = cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
createSteps(component:AnnotatedType):List<CompileStep> {
|
createSteps(component:DirectiveMetadata):List<CompileStep> {
|
||||||
var annotation: Component = component.annotation;
|
var annotation: Component = component.annotation;
|
||||||
var directives = annotation.template.directives;
|
var directives = annotation.template.directives;
|
||||||
var annotatedDirectives = ListWrapper.create();
|
var annotatedDirectives = ListWrapper.create();
|
||||||
for (var i=0; i<directives.length; i++) {
|
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);
|
return createDefaultSteps(this._parser, component, annotatedDirectives);
|
||||||
}
|
}
|
||||||
@ -75,12 +75,12 @@ export class Compiler {
|
|||||||
// transitively via the _templateLoader and store them in templateCache
|
// transitively via the _templateLoader and store them in templateCache
|
||||||
|
|
||||||
return PromiseWrapper.resolve(this.compileAllLoaded(
|
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.
|
// 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);
|
var rootProtoView = this._compilerCache.get(component.type);
|
||||||
if (isPresent(rootProtoView)) {
|
if (isPresent(rootProtoView)) {
|
||||||
return rootProtoView;
|
return rootProtoView;
|
||||||
|
@ -1,14 +1,18 @@
|
|||||||
import {Type, FIELD} from 'facade/lang';
|
import {Type, FIELD} from 'facade/lang';
|
||||||
import {Directive} from '../annotations/annotations'
|
import {Directive} from '../annotations/annotations'
|
||||||
|
import {ShadowDomStrategy} from './shadow_dom';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Combination of a type with the Directive annotation
|
* Combination of a type with the Directive annotation
|
||||||
*/
|
*/
|
||||||
export class AnnotatedType {
|
export class DirectiveMetadata {
|
||||||
type:Type;
|
type:Type;
|
||||||
annotation:Directive;
|
annotation:Directive;
|
||||||
constructor(type:Type, annotation:Directive) {
|
shadowDomStrategy:ShadowDomStrategy;
|
||||||
|
|
||||||
|
constructor(type:Type, annotation:Directive, shadowDomStrategy:ShadowDomStrategy) {
|
||||||
this.annotation = annotation;
|
this.annotation = annotation;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
|
this.shadowDomStrategy = shadowDomStrategy;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,27 +1,29 @@
|
|||||||
import {Type, isPresent, BaseException, stringify} from 'facade/lang';
|
import {Type, isPresent, BaseException, stringify} from 'facade/lang';
|
||||||
import {Directive} from '../annotations/annotations';
|
import {Directive, Component} from '../annotations/annotations';
|
||||||
import {AnnotatedType} from './annotated_type';
|
import {DirectiveMetadata} from './directive_metadata';
|
||||||
import {reflector} from 'reflection/reflection';
|
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 {
|
export class DirectiveMetadataReader {
|
||||||
annotatedType(type:Type):AnnotatedType {
|
read(type:Type):DirectiveMetadata {
|
||||||
var annotations = reflector.annotations(type);
|
var annotations = reflector.annotations(type);
|
||||||
if (isPresent(annotations)) {
|
if (isPresent(annotations)) {
|
||||||
for (var i=0; i<annotations.length; i++) {
|
for (var i=0; i<annotations.length; i++) {
|
||||||
var annotation = annotations[i];
|
var annotation = annotations[i];
|
||||||
|
|
||||||
|
if (annotation instanceof Component) {
|
||||||
|
return new DirectiveMetadata(type, annotation, this.parseShadowDomStrategy(annotation));
|
||||||
|
}
|
||||||
|
|
||||||
if (annotation instanceof Directive) {
|
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)}`);
|
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 {ProtoElementInjector} from './element_injector';
|
||||||
import {FIELD} from 'facade/lang';
|
import {FIELD} from 'facade/lang';
|
||||||
import {MapWrapper} from 'facade/collection';
|
import {MapWrapper} from 'facade/collection';
|
||||||
import {AnnotatedType} from './annotated_type';
|
import {DirectiveMetadata} from './directive_metadata';
|
||||||
import {List, Map} from 'facade/collection';
|
import {List, Map} from 'facade/collection';
|
||||||
import {ProtoView} from './view';
|
import {ProtoView} from './view';
|
||||||
|
|
||||||
export class ElementBinder {
|
export class ElementBinder {
|
||||||
protoElementInjector:ProtoElementInjector;
|
protoElementInjector:ProtoElementInjector;
|
||||||
componentDirective:AnnotatedType;
|
componentDirective:DirectiveMetadata;
|
||||||
templateDirective:AnnotatedType;
|
templateDirective:DirectiveMetadata;
|
||||||
textNodeIndices:List<int>;
|
textNodeIndices:List<int>;
|
||||||
hasElementPropertyBindings:boolean;
|
hasElementPropertyBindings:boolean;
|
||||||
nestedProtoView: ProtoView;
|
nestedProtoView: ProtoView;
|
||||||
events:Map;
|
events:Map;
|
||||||
constructor(
|
constructor(
|
||||||
protoElementInjector: ProtoElementInjector, componentDirective:AnnotatedType, templateDirective:AnnotatedType) {
|
protoElementInjector: ProtoElementInjector, componentDirective:DirectiveMetadata, templateDirective:DirectiveMetadata) {
|
||||||
this.protoElementInjector = protoElementInjector;
|
this.protoElementInjector = protoElementInjector;
|
||||||
this.componentDirective = componentDirective;
|
this.componentDirective = componentDirective;
|
||||||
this.templateDirective = templateDirective;
|
this.templateDirective = templateDirective;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import {List, Map, ListWrapper, MapWrapper} from 'facade/collection';
|
import {List, Map, ListWrapper, MapWrapper} from 'facade/collection';
|
||||||
import {Element, DOM} from 'facade/dom';
|
import {Element, DOM} from 'facade/dom';
|
||||||
import {int, isBlank, isPresent} from 'facade/lang';
|
import {int, isBlank, isPresent} from 'facade/lang';
|
||||||
import {AnnotatedType} from '../annotated_type';
|
import {DirectiveMetadata} from '../directive_metadata';
|
||||||
import {Decorator} from '../../annotations/annotations';
|
import {Decorator} from '../../annotations/annotations';
|
||||||
import {Component} from '../../annotations/annotations';
|
import {Component} from '../../annotations/annotations';
|
||||||
import {Template} from '../../annotations/annotations';
|
import {Template} from '../../annotations/annotations';
|
||||||
@ -24,9 +24,9 @@ export class CompileElement {
|
|||||||
propertyBindings:Map;
|
propertyBindings:Map;
|
||||||
eventBindings:Map;
|
eventBindings:Map;
|
||||||
variableBindings:Map;
|
variableBindings:Map;
|
||||||
decoratorDirectives:List<AnnotatedType>;
|
decoratorDirectives:List<DirectiveMetadata>;
|
||||||
templateDirective:AnnotatedType;
|
templateDirective:DirectiveMetadata;
|
||||||
componentDirective:AnnotatedType;
|
componentDirective:DirectiveMetadata;
|
||||||
isViewRoot:boolean;
|
isViewRoot:boolean;
|
||||||
hasBindings:boolean;
|
hasBindings:boolean;
|
||||||
inheritedProtoView:ProtoView;
|
inheritedProtoView:ProtoView;
|
||||||
@ -110,7 +110,7 @@ export class CompileElement {
|
|||||||
MapWrapper.set(this.eventBindings, eventName, expression);
|
MapWrapper.set(this.eventBindings, eventName, expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
addDirective(directive:AnnotatedType) {
|
addDirective(directive:DirectiveMetadata) {
|
||||||
var annotation = directive.annotation;
|
var annotation = directive.annotation;
|
||||||
if (annotation instanceof Decorator) {
|
if (annotation instanceof Decorator) {
|
||||||
if (isBlank(this.decoratorDirectives)) {
|
if (isBlank(this.decoratorDirectives)) {
|
||||||
|
@ -4,7 +4,7 @@ import {Element, Node, DOM} from 'facade/dom';
|
|||||||
import {CompileElement} from './compile_element';
|
import {CompileElement} from './compile_element';
|
||||||
import {CompileControl} from './compile_control';
|
import {CompileControl} from './compile_control';
|
||||||
import {CompileStep} from './compile_step';
|
import {CompileStep} from './compile_step';
|
||||||
import {AnnotatedType} from '../annotated_type';
|
import {DirectiveMetadata} from '../directive_metadata';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CompilePipeline for executing CompileSteps recursively for
|
* CompilePipeline for executing CompileSteps recursively for
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import {CompileElement} from './compile_element';
|
import {CompileElement} from './compile_element';
|
||||||
import {CompileControl} from './compile_control';
|
import {CompileControl} from './compile_control';
|
||||||
import {AnnotatedType} from '../annotated_type';
|
import {DirectiveMetadata} from '../directive_metadata';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* One part of the compile process.
|
* One part of the compile process.
|
||||||
|
@ -9,7 +9,7 @@ import {ElementBindingMarker} from './element_binding_marker';
|
|||||||
import {ProtoViewBuilder} from './proto_view_builder';
|
import {ProtoViewBuilder} from './proto_view_builder';
|
||||||
import {ProtoElementInjectorBuilder} from './proto_element_injector_builder';
|
import {ProtoElementInjectorBuilder} from './proto_element_injector_builder';
|
||||||
import {ElementBinderBuilder} from './element_binder_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';
|
import {stringify} from 'facade/lang';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -17,8 +17,8 @@ import {stringify} from 'facade/lang';
|
|||||||
* Takes in an HTMLElement and produces the ProtoViews,
|
* Takes in an HTMLElement and produces the ProtoViews,
|
||||||
* ProtoElementInjectors and ElementBinders in the end.
|
* ProtoElementInjectors and ElementBinders in the end.
|
||||||
*/
|
*/
|
||||||
export function createDefaultSteps(parser:Parser, compiledComponent: AnnotatedType,
|
export function createDefaultSteps(parser:Parser, compiledComponent: DirectiveMetadata,
|
||||||
directives: List<AnnotatedType>) {
|
directives: List<DirectiveMetadata>) {
|
||||||
var compilationUnit = stringify(compiledComponent.type);
|
var compilationUnit = stringify(compiledComponent.type);
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
@ -4,7 +4,7 @@ import {TemplateElement} from 'facade/dom';
|
|||||||
import {SelectorMatcher} from '../selector';
|
import {SelectorMatcher} from '../selector';
|
||||||
import {CssSelector} from '../selector';
|
import {CssSelector} from '../selector';
|
||||||
|
|
||||||
import {AnnotatedType} from '../annotated_type';
|
import {DirectiveMetadata} from '../directive_metadata';
|
||||||
import {Template} from '../../annotations/annotations';
|
import {Template} from '../../annotations/annotations';
|
||||||
import {Component} from '../../annotations/annotations';
|
import {Component} from '../../annotations/annotations';
|
||||||
import {CompileStep} from './compile_step';
|
import {CompileStep} from './compile_step';
|
||||||
@ -28,13 +28,13 @@ import {CompileControl} from './compile_control';
|
|||||||
*/
|
*/
|
||||||
export class DirectiveParser extends CompileStep {
|
export class DirectiveParser extends CompileStep {
|
||||||
_selectorMatcher:SelectorMatcher;
|
_selectorMatcher:SelectorMatcher;
|
||||||
constructor(directives:List<AnnotatedType>) {
|
constructor(directives:List<DirectiveMetadata>) {
|
||||||
this._selectorMatcher = new SelectorMatcher();
|
this._selectorMatcher = new SelectorMatcher();
|
||||||
for (var i=0; i<directives.length; i++) {
|
for (var i=0; i<directives.length; i++) {
|
||||||
var annotatedType = directives[i];
|
var directiveMetadata = directives[i];
|
||||||
this._selectorMatcher.addSelectable(
|
this._selectorMatcher.addSelectable(
|
||||||
CssSelector.parse(annotatedType.annotation.selector),
|
CssSelector.parse(directiveMetadata.annotation.selector),
|
||||||
annotatedType
|
directiveMetadata
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ import {Parser} from 'change_detection/parser/parser';
|
|||||||
import {ProtoRecordRange} from 'change_detection/record_range';
|
import {ProtoRecordRange} from 'change_detection/record_range';
|
||||||
|
|
||||||
import {Component, Directive} from '../../annotations/annotations';
|
import {Component, Directive} from '../../annotations/annotations';
|
||||||
import {AnnotatedType} from '../annotated_type';
|
import {DirectiveMetadata} from '../directive_metadata';
|
||||||
import {ProtoView, ElementPropertyMemento, DirectivePropertyMemento} from '../view';
|
import {ProtoView, ElementPropertyMemento, DirectivePropertyMemento} from '../view';
|
||||||
import {ProtoElementInjector} from '../element_injector';
|
import {ProtoElementInjector} from '../element_injector';
|
||||||
import {ElementBinder} from '../element_binder';
|
import {ElementBinder} from '../element_binder';
|
||||||
|
9
modules/core/src/compiler/shadow_dom.dart
Normal file
9
modules/core/src/compiler/shadow_dom.dart
Normal 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();
|
5
modules/core/src/compiler/shadow_dom.es6
Normal file
5
modules/core/src/compiler/shadow_dom.es6
Normal 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();
|
30
modules/core/src/compiler/shadow_dom_strategy.js
Normal file
30
modules/core/src/compiler/shadow_dom_strategy.js
Normal 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]);
|
||||||
|
}
|
||||||
|
}
|
@ -6,7 +6,7 @@ import {AST} from 'change_detection/parser/ast';
|
|||||||
|
|
||||||
import {ProtoElementInjector, ElementInjector, PreBuiltObjects} from './element_injector';
|
import {ProtoElementInjector, ElementInjector, PreBuiltObjects} from './element_injector';
|
||||||
import {ElementBinder} from './element_binder';
|
import {ElementBinder} from './element_binder';
|
||||||
import {AnnotatedType} from './annotated_type';
|
import {DirectiveMetadata} from './directive_metadata';
|
||||||
import {SetterFn} from 'reflection/types';
|
import {SetterFn} from 'reflection/types';
|
||||||
import {FIELD, IMPLEMENTS, int, isPresent, isBlank, BaseException} from 'facade/lang';
|
import {FIELD, IMPLEMENTS, int, isPresent, isBlank, BaseException} from 'facade/lang';
|
||||||
import {Injector} from 'di/di';
|
import {Injector} from 'di/di';
|
||||||
@ -350,7 +350,8 @@ export class ProtoView {
|
|||||||
if (isPresent(binder.componentDirective)) {
|
if (isPresent(binder.componentDirective)) {
|
||||||
var childView = binder.nestedProtoView.instantiate(elementInjector);
|
var childView = binder.nestedProtoView.instantiate(elementInjector);
|
||||||
view.recordRange.addRange(childView.recordRange);
|
view.recordRange.addRange(childView.recordRange);
|
||||||
ViewPort.moveViewNodesIntoParent(element.createShadowRoot(), childView);
|
|
||||||
|
binder.componentDirective.shadowDomStrategy.attachTemplate(element, childView);
|
||||||
ListWrapper.push(componentChildViews, childView);
|
ListWrapper.push(componentChildViews, childView);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -367,7 +368,7 @@ export class ProtoView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bindElement(protoElementInjector:ProtoElementInjector,
|
bindElement(protoElementInjector:ProtoElementInjector,
|
||||||
componentDirective:AnnotatedType = null, templateDirective:AnnotatedType = null):ElementBinder {
|
componentDirective:DirectiveMetadata = null, templateDirective:DirectiveMetadata = null):ElementBinder {
|
||||||
var elBinder = new ElementBinder(protoElementInjector, componentDirective, templateDirective);
|
var elBinder = new ElementBinder(protoElementInjector, componentDirective, templateDirective);
|
||||||
ListWrapper.push(this.elementBinders, elBinder);
|
ListWrapper.push(this.elementBinders, elBinder);
|
||||||
return elBinder;
|
return elBinder;
|
||||||
@ -434,7 +435,7 @@ export class ProtoView {
|
|||||||
// and the component template is already compiled into protoView.
|
// and the component template is already compiled into protoView.
|
||||||
// Used for bootstrapping.
|
// Used for bootstrapping.
|
||||||
static createRootProtoView(protoView: ProtoView,
|
static createRootProtoView(protoView: ProtoView,
|
||||||
insertionElement, rootComponentAnnotatedType: AnnotatedType): ProtoView {
|
insertionElement, rootComponentAnnotatedType: DirectiveMetadata): ProtoView {
|
||||||
DOM.addClass(insertionElement, 'ng-binding');
|
DOM.addClass(insertionElement, 'ng-binding');
|
||||||
var rootProtoView = new ProtoView(insertionElement, new ProtoRecordRange());
|
var rootProtoView = new ProtoView(insertionElement, new ProtoRecordRange());
|
||||||
rootProtoView.instantiateInPlace = true;
|
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) {
|
static moveViewNodesAfterSibling(sibling, view) {
|
||||||
for (var i = view.nodes.length - 1; i >= 0; --i) {
|
for (var i = view.nodes.length - 1; i >= 0; --i) {
|
||||||
DOM.insertAfter(sibling, view.nodes[i]);
|
DOM.insertAfter(sibling, view.nodes[i]);
|
||||||
|
@ -66,7 +66,7 @@ export function main() {
|
|||||||
current.inheritedProtoView = new ProtoView(current.element, null);
|
current.inheritedProtoView = new ProtoView(current.element, null);
|
||||||
current.inheritedElementBinder = current.inheritedProtoView.bindElement(null);
|
current.inheritedElementBinder = current.inheritedProtoView.bindElement(null);
|
||||||
if (current.element === mainEl) {
|
if (current.element === mainEl) {
|
||||||
current.componentDirective = reader.annotatedType(NestedComponent);
|
current.componentDirective = reader.read(NestedComponent);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
compiler.compile(MainComponent, mainEl).then( (protoView) => {
|
compiler.compile(MainComponent, mainEl).then( (protoView) => {
|
||||||
@ -97,7 +97,7 @@ export function main() {
|
|||||||
var compiler = createCompiler( (parent, current, control) => {
|
var compiler = createCompiler( (parent, current, control) => {
|
||||||
current.inheritedProtoView = new ProtoView(current.element, null);
|
current.inheritedProtoView = new ProtoView(current.element, null);
|
||||||
current.inheritedElementBinder = current.inheritedProtoView.bindElement(null);
|
current.inheritedElementBinder = current.inheritedProtoView.bindElement(null);
|
||||||
current.componentDirective = reader.annotatedType(RecursiveComponent);
|
current.componentDirective = reader.read(RecursiveComponent);
|
||||||
});
|
});
|
||||||
compiler.compile(RecursiveComponent, null).then( (protoView) => {
|
compiler.compile(RecursiveComponent, null).then( (protoView) => {
|
||||||
expect(protoView.elementBinders[0].nestedProtoView).toBe(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 {ddescribe, describe, it, iit, expect, beforeEach} from 'test_lib/test_lib';
|
||||||
import {DirectiveMetadataReader} from 'core/compiler/directive_metadata_reader';
|
import {DirectiveMetadataReader} from 'core/compiler/directive_metadata_reader';
|
||||||
import {Decorator} from 'core/annotations/annotations';
|
import {Decorator, Component} from 'core/annotations/annotations';
|
||||||
import {AnnotatedType} from 'core/compiler/annotated_type';
|
import {DirectiveMetadata} from 'core/compiler/directive_metadata';
|
||||||
|
import {ShadowDomEmulated, ShadowDomNative} from 'core/compiler/shadow_dom';
|
||||||
|
|
||||||
@Decorator({
|
@Decorator({
|
||||||
selector: 'someSelector'
|
selector: 'someSelector'
|
||||||
@ -9,28 +10,50 @@ import {AnnotatedType} from 'core/compiler/annotated_type';
|
|||||||
class SomeDirective {
|
class SomeDirective {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'someSelector'
|
||||||
|
})
|
||||||
|
class ComponentWithoutExplicitShadowDomStrategy {}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'someSelector',
|
||||||
|
shadowDom: ShadowDomEmulated
|
||||||
|
})
|
||||||
|
class ComponentWithExplicitShadowDomStrategy {}
|
||||||
|
|
||||||
class SomeDirectiveWithoutAnnotation {
|
class SomeDirectiveWithoutAnnotation {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function main() {
|
export function main() {
|
||||||
describe("DirectiveMetadataReader", () => {
|
describe("DirectiveMetadataReader", () => {
|
||||||
var rader;
|
var reader;
|
||||||
|
|
||||||
beforeEach( () => {
|
beforeEach( () => {
|
||||||
rader = new DirectiveMetadataReader();
|
reader = new DirectiveMetadataReader();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should read out the annotation', () => {
|
it('should read out the annotation', () => {
|
||||||
var annoatedDirective = rader.annotatedType(SomeDirective);
|
var directiveMetadata = reader.read(SomeDirective);
|
||||||
expect(annoatedDirective).toEqual(
|
expect(directiveMetadata).toEqual(
|
||||||
new AnnotatedType(SomeDirective, new Decorator({selector: 'someSelector'})));
|
new DirectiveMetadata(SomeDirective, new Decorator({selector: 'someSelector'}), null));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw if not matching annotation is found', () => {
|
it('should throw if not matching annotation is found', () => {
|
||||||
expect(() => {
|
expect(() => {
|
||||||
rader.annotatedType(SomeDirectiveWithoutAnnotation);
|
reader.read(SomeDirectiveWithoutAnnotation);
|
||||||
}).toThrowError('No Directive annotation found on 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 parser = new Parser(new Lexer());
|
||||||
var annotatedDirectives = ListWrapper.create();
|
var annotatedDirectives = ListWrapper.create();
|
||||||
for (var i=0; i<directives.length; i++) {
|
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) => {
|
return new CompilePipeline([new MockStep((parent, current, control) => {
|
||||||
@ -53,7 +53,7 @@ export function main() {
|
|||||||
describe('component directives', () => {
|
describe('component directives', () => {
|
||||||
it('should detect them in attributes', () => {
|
it('should detect them in attributes', () => {
|
||||||
var results = createPipeline().process(createElement('<div some-comp></div>'));
|
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', () => {
|
it('should detect them in property bindings', () => {
|
||||||
@ -61,7 +61,7 @@ export function main() {
|
|||||||
'some-comp': 'someExpr'
|
'some-comp': 'someExpr'
|
||||||
}});
|
}});
|
||||||
var results = pipeline.process(createElement('<div></div>'));
|
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', () => {
|
it('should detect them in variable bindings', () => {
|
||||||
@ -69,7 +69,7 @@ export function main() {
|
|||||||
'some-comp': 'someExpr'
|
'some-comp': 'someExpr'
|
||||||
}});
|
}});
|
||||||
var results = pipeline.process(createElement('<div></div>'));
|
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', () => {
|
it('should not allow multiple component directives on the same element', () => {
|
||||||
@ -92,7 +92,7 @@ export function main() {
|
|||||||
describe('template directives', () => {
|
describe('template directives', () => {
|
||||||
it('should detect them in attributes', () => {
|
it('should detect them in attributes', () => {
|
||||||
var results = createPipeline().process(createElement('<template some-templ></template>'));
|
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', () => {
|
it('should detect them in property bindings', () => {
|
||||||
@ -100,7 +100,7 @@ export function main() {
|
|||||||
'some-templ': 'someExpr'
|
'some-templ': 'someExpr'
|
||||||
}});
|
}});
|
||||||
var results = pipeline.process(createElement('<template></template>'));
|
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', () => {
|
it('should detect them in variable bindings', () => {
|
||||||
@ -108,7 +108,7 @@ export function main() {
|
|||||||
'some-templ': 'someExpr'
|
'some-templ': 'someExpr'
|
||||||
}});
|
}});
|
||||||
var results = pipeline.process(createElement('<template></template>'));
|
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', () => {
|
it('should not allow multiple template directives on the same element', () => {
|
||||||
@ -131,7 +131,7 @@ export function main() {
|
|||||||
describe('decorator directives', () => {
|
describe('decorator directives', () => {
|
||||||
it('should detect them in attributes', () => {
|
it('should detect them in attributes', () => {
|
||||||
var results = createPipeline().process(createElement('<div some-decor></div>'));
|
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', () => {
|
it('should detect them in property bindings', () => {
|
||||||
@ -139,7 +139,7 @@ export function main() {
|
|||||||
'some-decor': 'someExpr'
|
'some-decor': 'someExpr'
|
||||||
}});
|
}});
|
||||||
var results = pipeline.process(createElement('<div></div>'));
|
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', () => {
|
it('should detect them in variable bindings', () => {
|
||||||
@ -147,7 +147,7 @@ export function main() {
|
|||||||
'some-decor': 'someExpr'
|
'some-decor': 'someExpr'
|
||||||
}});
|
}});
|
||||||
var results = pipeline.process(createElement('<div></div>'));
|
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', () => {
|
it('should not allow decorator directives on <template> elements', () => {
|
||||||
|
@ -59,7 +59,7 @@ export function main() {
|
|||||||
if (isPresent(current.element.getAttribute('directives'))) {
|
if (isPresent(current.element.getAttribute('directives'))) {
|
||||||
hasBinding = true;
|
hasBinding = true;
|
||||||
for (var i=0; i<directives.length; i++) {
|
for (var i=0; i<directives.length; i++) {
|
||||||
current.addDirective(reflector.annotatedType(directives[i]));
|
current.addDirective(reflector.read(directives[i]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (hasBinding) {
|
if (hasBinding) {
|
||||||
|
@ -32,7 +32,7 @@ export function main() {
|
|||||||
}
|
}
|
||||||
if (isPresent(directives)) {
|
if (isPresent(directives)) {
|
||||||
for (var i=0; i<directives.length; i++) {
|
for (var i=0; i<directives.length; i++) {
|
||||||
current.addDirective(reader.annotatedType(directives[i]));
|
current.addDirective(reader.read(directives[i]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}), new ElementBindingMarker()
|
}), new ElementBindingMarker()
|
||||||
|
@ -32,7 +32,7 @@ export function main() {
|
|||||||
}
|
}
|
||||||
if (isPresent(current.element.getAttribute('directives'))) {
|
if (isPresent(current.element.getAttribute('directives'))) {
|
||||||
for (var i=0; i<directives.length; i++) {
|
for (var i=0; i<directives.length; i++) {
|
||||||
current.addDirective(reader.annotatedType(directives[i]));
|
current.addDirective(reader.read(directives[i]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
current.inheritedProtoView = protoView;
|
current.inheritedProtoView = protoView;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import {describe, xit, it, expect, beforeEach, ddescribe, iit} from 'test_lib/test_lib';
|
import {describe, xit, it, expect, beforeEach, ddescribe, iit} from 'test_lib/test_lib';
|
||||||
import {ProtoView, ElementPropertyMemento, DirectivePropertyMemento} from 'core/compiler/view';
|
import {ProtoView, ElementPropertyMemento, DirectivePropertyMemento} from 'core/compiler/view';
|
||||||
import {ProtoElementInjector, ElementInjector} from 'core/compiler/element_injector';
|
import {ProtoElementInjector, ElementInjector} from 'core/compiler/element_injector';
|
||||||
|
import {ShadowDomEmulated} from 'core/compiler/shadow_dom';
|
||||||
import {DirectiveMetadataReader} from 'core/compiler/directive_metadata_reader';
|
import {DirectiveMetadataReader} from 'core/compiler/directive_metadata_reader';
|
||||||
import {Component, Decorator, Template} from 'core/annotations/annotations';
|
import {Component, Decorator, Template} from 'core/annotations/annotations';
|
||||||
import {OnChange} from 'core/core';
|
import {OnChange} from 'core/core';
|
||||||
@ -29,8 +30,8 @@ export function main() {
|
|||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
parser = new Parser(new Lexer());
|
parser = new Parser(new Lexer());
|
||||||
someComponentDirective = new DirectiveMetadataReader().annotatedType(SomeComponent);
|
someComponentDirective = new DirectiveMetadataReader().read(SomeComponent);
|
||||||
someTemplateDirective = new DirectiveMetadataReader().annotatedType(SomeTemplate);
|
someTemplateDirective = new DirectiveMetadataReader().read(SomeTemplate);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('instatiated from protoView', () => {
|
describe('instatiated from protoView', () => {
|
||||||
@ -258,15 +259,6 @@ export function main() {
|
|||||||
return view;
|
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', () => {
|
it('should expose component services to the component', () => {
|
||||||
var subpv = new ProtoView(createElement('<span></span>'), new ProtoRecordRange());
|
var subpv = new ProtoView(createElement('<span></span>'), new ProtoRecordRange());
|
||||||
var pv = createComponentWithSubPV(subpv);
|
var pv = createComponentWithSubPV(subpv);
|
||||||
@ -316,6 +308,28 @@ export function main() {
|
|||||||
view.componentChildViews.forEach(
|
view.componentChildViews.forEach(
|
||||||
(view) => expectViewHasNoDirectiveInstances(view));
|
(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', () => {
|
describe('with template views', () => {
|
||||||
@ -485,6 +499,12 @@ class SomeComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
shadowDom: ShadowDomEmulated
|
||||||
|
})
|
||||||
|
class SomeComponentWithEmulatedShadowDom {
|
||||||
|
}
|
||||||
|
|
||||||
@Decorator({
|
@Decorator({
|
||||||
selector: '[dec]'
|
selector: '[dec]'
|
||||||
})
|
})
|
||||||
|
@ -47,6 +47,9 @@ class DOM {
|
|||||||
static List<Node> childNodes(el) {
|
static List<Node> childNodes(el) {
|
||||||
return el.childNodes;
|
return el.childNodes;
|
||||||
}
|
}
|
||||||
|
static clearNodes(el) {
|
||||||
|
el.nodes = [];
|
||||||
|
}
|
||||||
static appendChild(el, node) {
|
static appendChild(el, node) {
|
||||||
el.append(node);
|
el.append(node);
|
||||||
}
|
}
|
||||||
|
@ -40,6 +40,9 @@ export class DOM {
|
|||||||
static childNodes(el):NodeList {
|
static childNodes(el):NodeList {
|
||||||
return el.childNodes;
|
return el.childNodes;
|
||||||
}
|
}
|
||||||
|
static clearNodes(el) {
|
||||||
|
el.innerHTML = "";
|
||||||
|
}
|
||||||
static appendChild(el, node) {
|
static appendChild(el, node) {
|
||||||
el.appendChild(node);
|
el.appendChild(node);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user