feat(compiler, ShadowDom): adds TemplateLoader using XHR.
Also adds css shimming for emulated shadow dom and makes the shadowDom strategy global to the application.
This commit is contained in:
parent
fcbdf02767
commit
746f85a621
|
@ -50,7 +50,8 @@ module.exports = function(config) {
|
||||||
'/packages/directives': 'http://localhost:9877/base/modules/directives',
|
'/packages/directives': 'http://localhost:9877/base/modules/directives',
|
||||||
'/packages/facade': 'http://localhost:9877/base/modules/facade',
|
'/packages/facade': 'http://localhost:9877/base/modules/facade',
|
||||||
'/packages/forms': 'http://localhost:9877/base/modules/forms',
|
'/packages/forms': 'http://localhost:9877/base/modules/forms',
|
||||||
'/packages/test_lib': 'http://localhost:9877/base/modules/test_lib'
|
'/packages/test_lib': 'http://localhost:9877/base/modules/test_lib',
|
||||||
|
'/packages/mock': 'http://localhost:9877/base/modules/mock',
|
||||||
},
|
},
|
||||||
|
|
||||||
preprocessors: {
|
preprocessors: {
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
import {ABSTRACT, CONST, normalizeBlank} from 'angular2/src/facade/lang';
|
import {ABSTRACT, CONST, normalizeBlank} from 'angular2/src/facade/lang';
|
||||||
import {List} from 'angular2/src/facade/collection';
|
import {List} from 'angular2/src/facade/collection';
|
||||||
import {TemplateConfig} from './template_config';
|
import {TemplateConfig} from './template_config';
|
||||||
import {ShadowDomStrategy} from '../compiler/shadow_dom';
|
|
||||||
|
|
||||||
|
|
||||||
@ABSTRACT()
|
@ABSTRACT()
|
||||||
export class Directive {
|
export class Directive {
|
||||||
|
@ -40,7 +38,6 @@ 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;
|
|
||||||
lifecycle:any; //List
|
lifecycle:any; //List
|
||||||
|
|
||||||
@CONST()
|
@CONST()
|
||||||
|
@ -52,7 +49,6 @@ export class Component extends Directive {
|
||||||
shadowDomServices,
|
shadowDomServices,
|
||||||
componentServices,
|
componentServices,
|
||||||
implementsTypes,
|
implementsTypes,
|
||||||
shadowDom,
|
|
||||||
lifecycle
|
lifecycle
|
||||||
}:{
|
}:{
|
||||||
selector:String,
|
selector:String,
|
||||||
|
@ -62,7 +58,6 @@ export class Component extends Directive {
|
||||||
shadowDomServices:List,
|
shadowDomServices:List,
|
||||||
componentServices:List,
|
componentServices:List,
|
||||||
implementsTypes:List,
|
implementsTypes:List,
|
||||||
shadowDom:ShadowDomStrategy,
|
|
||||||
lifecycle:List
|
lifecycle:List
|
||||||
}={})
|
}={})
|
||||||
{
|
{
|
||||||
|
@ -78,7 +73,6 @@ 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;
|
|
||||||
this.lifecycle = lifecycle;
|
this.lifecycle = lifecycle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,9 @@ import {List, ListWrapper} from 'angular2/src/facade/collection';
|
||||||
import {PromiseWrapper} from 'angular2/src/facade/async';
|
import {PromiseWrapper} from 'angular2/src/facade/async';
|
||||||
import {VmTurnZone} from 'angular2/src/core/zone/vm_turn_zone';
|
import {VmTurnZone} from 'angular2/src/core/zone/vm_turn_zone';
|
||||||
import {LifeCycle} from 'angular2/src/core/life_cycle/life_cycle';
|
import {LifeCycle} from 'angular2/src/core/life_cycle/life_cycle';
|
||||||
|
import {ShadowDomStrategy, NativeShadowDomStrategy} from 'angular2/src/core/compiler/shadow_dom_strategy';
|
||||||
|
import {XHR} from 'angular2/src/core/compiler/xhr/xhr';
|
||||||
|
import {XHRImpl} from 'angular2/src/core/compiler/xhr/xhr_impl';
|
||||||
|
|
||||||
var _rootInjector: Injector;
|
var _rootInjector: Injector;
|
||||||
|
|
||||||
|
@ -24,7 +27,9 @@ var _rootBindings = [
|
||||||
TemplateLoader,
|
TemplateLoader,
|
||||||
DirectiveMetadataReader,
|
DirectiveMetadataReader,
|
||||||
Parser,
|
Parser,
|
||||||
Lexer
|
Lexer,
|
||||||
|
bind(ShadowDomStrategy).toValue(new NativeShadowDomStrategy()),
|
||||||
|
bind(XHR).toValue(new XHRImpl()),
|
||||||
];
|
];
|
||||||
|
|
||||||
export var appViewToken = new OpaqueToken('AppView');
|
export var appViewToken = new OpaqueToken('AppView');
|
||||||
|
@ -53,11 +58,12 @@ function _injectorBindings(appComponentType) {
|
||||||
}, [appComponentAnnotatedTypeToken, appDocumentToken]),
|
}, [appComponentAnnotatedTypeToken, appDocumentToken]),
|
||||||
|
|
||||||
bind(appViewToken).toAsyncFactory((changeDetection, compiler, injector, appElement,
|
bind(appViewToken).toAsyncFactory((changeDetection, compiler, injector, appElement,
|
||||||
appComponentAnnotatedType) => {
|
appComponentAnnotatedType, strategy) => {
|
||||||
return compiler.compile(appComponentAnnotatedType.type, null).then(
|
return compiler.compile(appComponentAnnotatedType.type, null).then(
|
||||||
(protoView) => {
|
(protoView) => {
|
||||||
var appProtoView = ProtoView.createRootProtoView(protoView,
|
var appProtoView = ProtoView.createRootProtoView(protoView, appElement,
|
||||||
appElement, appComponentAnnotatedType, changeDetection.createProtoChangeDetector('root'));
|
appComponentAnnotatedType, changeDetection.createProtoChangeDetector('root'),
|
||||||
|
strategy);
|
||||||
// The light Dom of the app element is not considered part of
|
// The light Dom of the app element is not considered part of
|
||||||
// the angular application. Thus the context and lightDomInjector are
|
// the angular application. Thus the context and lightDomInjector are
|
||||||
// empty.
|
// empty.
|
||||||
|
@ -65,7 +71,8 @@ function _injectorBindings(appComponentType) {
|
||||||
view.hydrate(injector, null, new Object());
|
view.hydrate(injector, null, new Object());
|
||||||
return view;
|
return view;
|
||||||
});
|
});
|
||||||
}, [ChangeDetection, Compiler, Injector, appElementToken, appComponentAnnotatedTypeToken]),
|
}, [ChangeDetection, Compiler, Injector, appElementToken, appComponentAnnotatedTypeToken,
|
||||||
|
ShadowDomStrategy]),
|
||||||
|
|
||||||
bind(appChangeDetectorToken).toFactory((rootView) => rootView.changeDetector,
|
bind(appChangeDetectorToken).toFactory((rootView) => rootView.changeDetector,
|
||||||
[appViewToken]),
|
[appViewToken]),
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import {Type, FIELD, isBlank, isPresent, BaseException, stringify} from 'angular2/src/facade/lang';
|
import {Type, isBlank, isPresent, BaseException, normalizeBlank, stringify} from 'angular2/src/facade/lang';
|
||||||
import {Promise, PromiseWrapper} from 'angular2/src/facade/async';
|
import {Promise, PromiseWrapper} from 'angular2/src/facade/async';
|
||||||
import {List, ListWrapper, MapWrapper} from 'angular2/src/facade/collection';
|
import {List, ListWrapper, Map, MapWrapper} from 'angular2/src/facade/collection';
|
||||||
import {DOM, Element} from 'angular2/src/facade/dom';
|
import {DOM, Element} from 'angular2/src/facade/dom';
|
||||||
|
|
||||||
import {ChangeDetection, Parser} from 'angular2/change_detection';
|
import {ChangeDetection, Parser} from 'angular2/change_detection';
|
||||||
|
@ -14,6 +14,7 @@ import {TemplateLoader} from './template_loader';
|
||||||
import {DirectiveMetadata} from './directive_metadata';
|
import {DirectiveMetadata} from './directive_metadata';
|
||||||
import {Component} from '../annotations/annotations';
|
import {Component} from '../annotations/annotations';
|
||||||
import {Content} from './shadow_dom_emulation/content_tag';
|
import {Content} from './shadow_dom_emulation/content_tag';
|
||||||
|
import {ShadowDomStrategy} from './shadow_dom_strategy';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cache that stores the ProtoView of the template of a component.
|
* Cache that stores the ProtoView of the template of a component.
|
||||||
|
@ -31,15 +32,11 @@ export class CompilerCache {
|
||||||
|
|
||||||
get(component:Type):ProtoView {
|
get(component:Type):ProtoView {
|
||||||
var result = MapWrapper.get(this._cache, component);
|
var result = MapWrapper.get(this._cache, component);
|
||||||
if (isBlank(result)) {
|
return normalizeBlank(result);
|
||||||
// need to normalize undefined to null so that type checking passes :-(
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
clear() {
|
clear() {
|
||||||
this._cache = MapWrapper.create();
|
MapWrapper.clear(this._cache);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,59 +50,107 @@ export class Compiler {
|
||||||
_parser:Parser;
|
_parser:Parser;
|
||||||
_compilerCache:CompilerCache;
|
_compilerCache:CompilerCache;
|
||||||
_changeDetection:ChangeDetection;
|
_changeDetection:ChangeDetection;
|
||||||
|
_templateLoader:TemplateLoader;
|
||||||
|
_compiling:Map<Type, Promise>;
|
||||||
|
_shadowDomStrategy: ShadowDomStrategy;
|
||||||
|
_shadowDomDirectives: List<DirectiveMetadata>;
|
||||||
|
|
||||||
constructor(changeDetection:ChangeDetection, templateLoader:TemplateLoader, reader: DirectiveMetadataReader, parser:Parser, cache:CompilerCache) {
|
constructor(changeDetection:ChangeDetection,
|
||||||
|
templateLoader:TemplateLoader,
|
||||||
|
reader: DirectiveMetadataReader,
|
||||||
|
parser:Parser,
|
||||||
|
cache:CompilerCache,
|
||||||
|
shadowDomStrategy: ShadowDomStrategy) {
|
||||||
this._changeDetection = changeDetection;
|
this._changeDetection = changeDetection;
|
||||||
this._reader = reader;
|
this._reader = reader;
|
||||||
this._parser = parser;
|
this._parser = parser;
|
||||||
this._compilerCache = cache;
|
this._compilerCache = cache;
|
||||||
|
this._templateLoader = templateLoader;
|
||||||
|
this._compiling = MapWrapper.create();
|
||||||
|
this._shadowDomStrategy = shadowDomStrategy;
|
||||||
|
this._shadowDomDirectives = [];
|
||||||
|
var types = shadowDomStrategy.polyfillDirectives();
|
||||||
|
for (var i = 0; i < types.length; i++) {
|
||||||
|
ListWrapper.push(this._shadowDomDirectives, reader.read(types[i]));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
createSteps(component:DirectiveMetadata):List<CompileStep> {
|
createSteps(component:DirectiveMetadata):List<CompileStep> {
|
||||||
var dirs = ListWrapper.map(component.componentDirectives, (d) => this._reader.read(d));
|
var directives = []
|
||||||
return createDefaultSteps(this._changeDetection, this._parser, component, dirs);
|
var cmpDirectives = ListWrapper.map(component.componentDirectives, (d) => this._reader.read(d));
|
||||||
|
directives = ListWrapper.concat(directives, cmpDirectives);
|
||||||
|
directives = ListWrapper.concat(directives, this._shadowDomDirectives);
|
||||||
|
return createDefaultSteps(this._changeDetection, this._parser, component, directives,
|
||||||
|
this._shadowDomStrategy);
|
||||||
}
|
}
|
||||||
|
|
||||||
compile(component:Type, templateRoot:Element = null):Promise<ProtoView> {
|
compile(component:Type, templateRoot:Element = null):Promise<ProtoView> {
|
||||||
var templateCache = null;
|
return this._compile(this._reader.read(component), templateRoot);
|
||||||
// TODO load all components that have urls
|
}
|
||||||
// transitively via the _templateLoader and store them in templateCache
|
|
||||||
|
|
||||||
return PromiseWrapper.resolve(this.compileAllLoaded(
|
_compile(cmpMetadata: DirectiveMetadata, templateRoot:Element = null) {
|
||||||
templateCache, this._reader.read(component), templateRoot)
|
var pvCached = this._compilerCache.get(cmpMetadata.type);
|
||||||
|
if (isPresent(pvCached)) {
|
||||||
|
// The component has already been compiled into a ProtoView,
|
||||||
|
// returns a resolved Promise.
|
||||||
|
return PromiseWrapper.resolve(pvCached);
|
||||||
|
}
|
||||||
|
|
||||||
|
var pvPromise = MapWrapper.get(this._compiling, cmpMetadata.type);
|
||||||
|
if (isPresent(pvPromise)) {
|
||||||
|
// The component is already being compiled, attach to the existing Promise
|
||||||
|
// instead of re-compiling the component.
|
||||||
|
// It happens when a template references a component multiple times.
|
||||||
|
return pvPromise;
|
||||||
|
}
|
||||||
|
|
||||||
|
var tplPromise = isBlank(templateRoot) ?
|
||||||
|
this._templateLoader.load(cmpMetadata) :
|
||||||
|
PromiseWrapper.resolve(templateRoot);
|
||||||
|
|
||||||
|
pvPromise = PromiseWrapper.then(tplPromise,
|
||||||
|
(el) => this._compileTemplate(el, cmpMetadata),
|
||||||
|
(_) => { throw new BaseException(`Failed to load the template for ${stringify(cmpMetadata.type)}`) }
|
||||||
|
);
|
||||||
|
|
||||||
|
MapWrapper.set(this._compiling, cmpMetadata.type, pvPromise);
|
||||||
|
|
||||||
|
return pvPromise;
|
||||||
|
}
|
||||||
|
|
||||||
|
_compileTemplate(template: Element, cmpMetadata): Promise<ProtoView> {
|
||||||
|
this._shadowDomStrategy.processTemplate(template, cmpMetadata);
|
||||||
|
var pipeline = new CompilePipeline(this.createSteps(cmpMetadata));
|
||||||
|
var compileElements = pipeline.process(template);
|
||||||
|
var protoView = compileElements[0].inheritedProtoView;
|
||||||
|
|
||||||
|
// Populate the cache before compiling the nested components,
|
||||||
|
// so that components can reference themselves in their template.
|
||||||
|
this._compilerCache.set(cmpMetadata.type, protoView);
|
||||||
|
MapWrapper.delete(this._compiling, cmpMetadata.type);
|
||||||
|
|
||||||
|
// Compile all the components from the template
|
||||||
|
var componentPromises = [];
|
||||||
|
for (var i = 0; i < compileElements.length; i++) {
|
||||||
|
var ce = compileElements[i];
|
||||||
|
if (isPresent(ce.componentDirective)) {
|
||||||
|
var componentPromise = this._compileNestedProtoView(ce);
|
||||||
|
ListWrapper.push(componentPromises, componentPromise);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The protoView is resolved after all the components in the template have been compiled.
|
||||||
|
return PromiseWrapper.then(PromiseWrapper.all(componentPromises),
|
||||||
|
(_) => protoView,
|
||||||
|
(e) => { throw new BaseException(`${e} -> Failed to compile ${stringify(cmpMetadata.type)}`) }
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// public so that we can compile in sync in performance tests.
|
_compileNestedProtoView(ce: CompileElement):Promise<ProtoView> {
|
||||||
compileAllLoaded(templateCache, component:DirectiveMetadata, templateRoot:Element = null):ProtoView {
|
var pvPromise = this._compile(ce.componentDirective);
|
||||||
var rootProtoView = this._compilerCache.get(component.type);
|
pvPromise.then(function(protoView) {
|
||||||
if (isPresent(rootProtoView)) {
|
ce.inheritedElementBinder.nestedProtoView = protoView;
|
||||||
return rootProtoView;
|
});
|
||||||
}
|
return pvPromise;
|
||||||
|
|
||||||
if (isBlank(templateRoot)) {
|
|
||||||
// TODO: read out the cache if templateRoot = null. Could contain:
|
|
||||||
// - templateRoot string
|
|
||||||
// - precompiled template
|
|
||||||
// - ProtoView
|
|
||||||
var annotation:any = component.annotation;
|
|
||||||
templateRoot = DOM.createTemplate(annotation.template.inline);
|
|
||||||
}
|
|
||||||
|
|
||||||
var pipeline = new CompilePipeline(this.createSteps(component));
|
|
||||||
var compileElements = pipeline.process(templateRoot);
|
|
||||||
rootProtoView = compileElements[0].inheritedProtoView;
|
|
||||||
// Save the rootProtoView before we recurse so that we are able
|
|
||||||
// to compile components that use themselves in their template.
|
|
||||||
this._compilerCache.set(component.type, rootProtoView);
|
|
||||||
|
|
||||||
for (var i=0; i<compileElements.length; i++) {
|
|
||||||
var ce = compileElements[i];
|
|
||||||
if (isPresent(ce.componentDirective)) {
|
|
||||||
ce.inheritedElementBinder.nestedProtoView = this.compileAllLoaded(templateCache, ce.componentDirective, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return rootProtoView;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import {Type} from 'angular2/src/facade/lang';
|
import {Type} from 'angular2/src/facade/lang';
|
||||||
import {Directive} from '../annotations/annotations'
|
import {Directive} from 'angular2/src/core/annotations/annotations'
|
||||||
import {List} from 'angular2/src/facade/collection'
|
import {List} from 'angular2/src/facade/collection'
|
||||||
import {ShadowDomStrategy} from './shadow_dom';
|
import {ShadowDomStrategy} from 'angular2/src/core/compiler/shadow_dom_strategy';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Combination of a type with the Directive annotation
|
* Combination of a type with the Directive annotation
|
||||||
|
@ -9,14 +9,13 @@ import {ShadowDomStrategy} from './shadow_dom';
|
||||||
export class DirectiveMetadata {
|
export class DirectiveMetadata {
|
||||||
type:Type;
|
type:Type;
|
||||||
annotation:Directive;
|
annotation:Directive;
|
||||||
shadowDomStrategy:ShadowDomStrategy;
|
|
||||||
componentDirectives:List<Type>;
|
componentDirectives:List<Type>;
|
||||||
|
|
||||||
constructor(type:Type, annotation:Directive, shadowDomStrategy:ShadowDomStrategy,
|
constructor(type:Type,
|
||||||
|
annotation:Directive,
|
||||||
componentDirectives:List<Type>) {
|
componentDirectives:List<Type>) {
|
||||||
this.annotation = annotation;
|
this.annotation = annotation;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.shadowDomStrategy = shadowDomStrategy;
|
|
||||||
this.componentDirectives = componentDirectives;
|
this.componentDirectives = componentDirectives;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ import {List, ListWrapper} from 'angular2/src/facade/collection';
|
||||||
import {Directive, Component} from '../annotations/annotations';
|
import {Directive, Component} from '../annotations/annotations';
|
||||||
import {DirectiveMetadata} from './directive_metadata';
|
import {DirectiveMetadata} from './directive_metadata';
|
||||||
import {reflector} from 'angular2/src/reflection/reflection';
|
import {reflector} from 'angular2/src/reflection/reflection';
|
||||||
import {ShadowDom, ShadowDomStrategy, ShadowDomNative} from './shadow_dom';
|
import {ShadowDom, ShadowDomStrategy, ShadowDomNative} from './shadow_dom_strategy';
|
||||||
|
|
||||||
export class DirectiveMetadataReader {
|
export class DirectiveMetadataReader {
|
||||||
read(type:Type):DirectiveMetadata {
|
read(type:Type):DirectiveMetadata {
|
||||||
|
@ -13,36 +13,23 @@ export class DirectiveMetadataReader {
|
||||||
var annotation = annotations[i];
|
var annotation = annotations[i];
|
||||||
|
|
||||||
if (annotation instanceof Component) {
|
if (annotation instanceof Component) {
|
||||||
var shadowDomStrategy = this.parseShadowDomStrategy(annotation);
|
|
||||||
return new DirectiveMetadata(
|
return new DirectiveMetadata(
|
||||||
type,
|
type,
|
||||||
annotation,
|
annotation,
|
||||||
shadowDomStrategy,
|
this.componentDirectivesMetadata(annotation)
|
||||||
this.componentDirectivesMetadata(annotation, shadowDomStrategy)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (annotation instanceof Directive) {
|
if (annotation instanceof Directive) {
|
||||||
return new DirectiveMetadata(type, annotation, null, null);
|
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{
|
componentDirectivesMetadata(annotation:Component):List<Type> {
|
||||||
return isPresent(annotation.shadowDom) ? annotation.shadowDom : ShadowDomNative;
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDirectivesMetadata(annotation:Component, shadowDomStrategy:ShadowDomStrategy):List<Type> {
|
|
||||||
var polyDirs = shadowDomStrategy.polyfillDirectives();
|
|
||||||
var template = annotation.template;
|
var template = annotation.template;
|
||||||
var templateDirs = isPresent(template) && isPresent(template.directives) ? template.directives : [];
|
return isPresent(template) && isPresent(template.directives) ? template.directives : [];
|
||||||
|
|
||||||
var res = [];
|
|
||||||
res = ListWrapper.concat(res, templateDirs)
|
|
||||||
res = ListWrapper.concat(res, polyDirs)
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ 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 {DirectiveMetadata} from 'angular2/src/core/compiler/directive_metadata';
|
import {DirectiveMetadata} from 'angular2/src/core/compiler/directive_metadata';
|
||||||
|
import {ShadowDomStrategy} from 'angular2/src/core/compiler/shadow_dom_strategy';
|
||||||
import {stringify} from 'angular2/src/facade/lang';
|
import {stringify} from 'angular2/src/facade/lang';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -21,7 +22,8 @@ export function createDefaultSteps(
|
||||||
changeDetection:ChangeDetection,
|
changeDetection:ChangeDetection,
|
||||||
parser:Parser,
|
parser:Parser,
|
||||||
compiledComponent: DirectiveMetadata,
|
compiledComponent: DirectiveMetadata,
|
||||||
directives: List<DirectiveMetadata>) {
|
directives: List<DirectiveMetadata>,
|
||||||
|
shadowDomStrategy: ShadowDomStrategy) {
|
||||||
|
|
||||||
var compilationUnit = stringify(compiledComponent.type);
|
var compilationUnit = stringify(compiledComponent.type);
|
||||||
|
|
||||||
|
@ -31,7 +33,7 @@ export function createDefaultSteps(
|
||||||
new DirectiveParser(directives),
|
new DirectiveParser(directives),
|
||||||
new TextInterpolationParser(parser, compilationUnit),
|
new TextInterpolationParser(parser, compilationUnit),
|
||||||
new ElementBindingMarker(),
|
new ElementBindingMarker(),
|
||||||
new ProtoViewBuilder(changeDetection),
|
new ProtoViewBuilder(changeDetection, shadowDomStrategy),
|
||||||
new ProtoElementInjectorBuilder(),
|
new ProtoElementInjectorBuilder(),
|
||||||
new ElementBinderBuilder()
|
new ElementBinderBuilder()
|
||||||
];
|
];
|
||||||
|
|
|
@ -10,6 +10,7 @@ import {Component} from '../../annotations/annotations';
|
||||||
import {CompileStep} from './compile_step';
|
import {CompileStep} from './compile_step';
|
||||||
import {CompileElement} from './compile_element';
|
import {CompileElement} from './compile_element';
|
||||||
import {CompileControl} from './compile_control';
|
import {CompileControl} from './compile_control';
|
||||||
|
import {ShadowDomStrategy} from '../shadow_dom_strategy';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses the directives on a single element. Assumes ViewSplitter has already created
|
* Parses the directives on a single element. Assumes ViewSplitter has already created
|
||||||
|
|
|
@ -7,6 +7,7 @@ import {ChangeDetection} from 'angular2/change_detection';
|
||||||
import {CompileStep} from './compile_step';
|
import {CompileStep} from './compile_step';
|
||||||
import {CompileElement} from './compile_element';
|
import {CompileElement} from './compile_element';
|
||||||
import {CompileControl} from './compile_control';
|
import {CompileControl} from './compile_control';
|
||||||
|
import {ShadowDomStrategy} from '../shadow_dom_strategy';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates ProtoViews and forwards variable bindings from parent to children.
|
* Creates ProtoViews and forwards variable bindings from parent to children.
|
||||||
|
@ -22,7 +23,9 @@ import {CompileControl} from './compile_control';
|
||||||
*/
|
*/
|
||||||
export class ProtoViewBuilder extends CompileStep {
|
export class ProtoViewBuilder extends CompileStep {
|
||||||
changeDetection:ChangeDetection;
|
changeDetection:ChangeDetection;
|
||||||
constructor(changeDetection:ChangeDetection) {
|
_shadowDomStrategy:ShadowDomStrategy;
|
||||||
|
constructor(changeDetection:ChangeDetection, shadowDomStrategy:ShadowDomStrategy) {
|
||||||
|
this._shadowDomStrategy = shadowDomStrategy;
|
||||||
this.changeDetection = changeDetection;
|
this.changeDetection = changeDetection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,7 +33,8 @@ export class ProtoViewBuilder extends CompileStep {
|
||||||
var inheritedProtoView = null;
|
var inheritedProtoView = null;
|
||||||
if (current.isViewRoot) {
|
if (current.isViewRoot) {
|
||||||
var protoChangeDetector = this.changeDetection.createProtoChangeDetector('dummy');
|
var protoChangeDetector = this.changeDetection.createProtoChangeDetector('dummy');
|
||||||
inheritedProtoView = new ProtoView(current.element, protoChangeDetector);
|
inheritedProtoView = new ProtoView(current.element, protoChangeDetector,
|
||||||
|
this._shadowDomStrategy);
|
||||||
if (isPresent(parent)) {
|
if (isPresent(parent)) {
|
||||||
if (isPresent(parent.inheritedElementBinder.nestedProtoView)) {
|
if (isPresent(parent.inheritedElementBinder.nestedProtoView)) {
|
||||||
throw new BaseException('Only one nested view per element is allowed');
|
throw new BaseException('Only one nested view per element is allowed');
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
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();
|
|
|
@ -1,5 +0,0 @@
|
||||||
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,431 @@
|
||||||
|
import {StringWrapper, RegExpWrapper, isPresent, BaseException, int} from 'angular2/src/facade/lang';
|
||||||
|
import {List, ListWrapper} from 'angular2/src/facade/collection';
|
||||||
|
|
||||||
|
export function shimCssText(css: string, tag: string) {
|
||||||
|
return new CssShim(tag).shimCssText(css);
|
||||||
|
}
|
||||||
|
|
||||||
|
var _HOST_RE = RegExpWrapper.create(':host', 'i');
|
||||||
|
var _HOST_TOKEN = '-host-element';
|
||||||
|
var _HOST_TOKEN_RE = RegExpWrapper.create('-host-element');
|
||||||
|
var _PAREN_SUFFIX = ')(?:\\((' +
|
||||||
|
'(?:\\([^)(]*\\)|[^)(]*)+?' +
|
||||||
|
')\\))?([^,{]*)';
|
||||||
|
var _COLON_HOST_RE = RegExpWrapper.create(`(${_HOST_TOKEN}${_PAREN_SUFFIX}`, 'im');
|
||||||
|
|
||||||
|
var _POLYFILL_NON_STRICT = 'polyfill-non-strict';
|
||||||
|
var _POLYFILL_UNSCOPED_NEXT_SELECTOR = 'polyfill-unscoped-next-selector';
|
||||||
|
var _POLYFILL_NEXT_SELECTOR = 'polyfill-next-selector';
|
||||||
|
var _CONTENT_RE = RegExpWrapper.create('[^}]*content:[\\s]*[\'"](.*?)[\'"][;\\s]*[^}]*}', 'im');
|
||||||
|
var _COMBINATORS = [
|
||||||
|
RegExpWrapper.create('/shadow/', 'i'),
|
||||||
|
RegExpWrapper.create('/shadow-deep/', 'i'),
|
||||||
|
RegExpWrapper.create('::shadow', 'i'),
|
||||||
|
RegExpWrapper.create('/deep/', 'i'),
|
||||||
|
];
|
||||||
|
var _COLON_SELECTORS = RegExpWrapper.create('(' + _HOST_TOKEN + ')(\\(.*\\))?(.*)', 'i');
|
||||||
|
var _SELECTOR_SPLITS = [' ', '>', '+', '~'];
|
||||||
|
var _SIMPLE_SELECTORS = RegExpWrapper.create('([^:]*)(:*)(.*)', 'i');
|
||||||
|
var _IS_SELECTORS = RegExpWrapper.create('\\[is=[\'"]([^\\]]*)[\'"]\\]', 'i');
|
||||||
|
|
||||||
|
var _$EOF = 0;
|
||||||
|
var _$LBRACE = 123;
|
||||||
|
var _$RBRACE = 125;
|
||||||
|
var _$TAB = 9;
|
||||||
|
var _$SPACE = 32;
|
||||||
|
var _$NBSP = 160;
|
||||||
|
|
||||||
|
export class CssShim {
|
||||||
|
_tag: string;
|
||||||
|
_attr: string;
|
||||||
|
|
||||||
|
constructor(tag: string) {
|
||||||
|
this._tag = tag;
|
||||||
|
this._attr = `[${tag}]`;
|
||||||
|
}
|
||||||
|
|
||||||
|
shimCssText(css: string): string {
|
||||||
|
var preprocessed = this.convertColonHost(css);
|
||||||
|
var rules = this.cssToRules(preprocessed);
|
||||||
|
return this.scopeRules(rules);
|
||||||
|
}
|
||||||
|
|
||||||
|
convertColonHost(css: string):string {
|
||||||
|
css = StringWrapper.replaceAll(css, _HOST_RE, _HOST_TOKEN);
|
||||||
|
|
||||||
|
var partReplacer = function(host, part, suffix) {
|
||||||
|
part = StringWrapper.replaceAll(part, _HOST_TOKEN_RE, '');
|
||||||
|
return `${host}${part}${suffix}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return StringWrapper.replaceAllMapped(css, _COLON_HOST_RE, function(m) {
|
||||||
|
var base = _HOST_TOKEN;
|
||||||
|
var inParens = m[2];
|
||||||
|
var rest = m[3];
|
||||||
|
|
||||||
|
if (isPresent(inParens)) {
|
||||||
|
var srcParts = inParens.split(',');
|
||||||
|
var dstParts = [];
|
||||||
|
|
||||||
|
for (var i = 0; i < srcParts.length; i++) {
|
||||||
|
var part = srcParts[i].trim();
|
||||||
|
if (part.length > 0) {
|
||||||
|
ListWrapper.push(dstParts, partReplacer(base, part, rest));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ListWrapper.join(dstParts, ',');
|
||||||
|
} else {
|
||||||
|
return `${base}${rest}`;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
cssToRules(css: string): List<_Rule> {
|
||||||
|
return new _Parser(css).parse();
|
||||||
|
}
|
||||||
|
|
||||||
|
scopeRules(rules: List<_Rule>): string {
|
||||||
|
var scopedRules = [];
|
||||||
|
var prevRule = null;
|
||||||
|
|
||||||
|
for (var i = 0; i < rules.length; i++) {
|
||||||
|
var rule = rules[i];
|
||||||
|
if (isPresent(prevRule) &&
|
||||||
|
prevRule.selectorText == _POLYFILL_NON_STRICT) {
|
||||||
|
ListWrapper.push(scopedRules, this.scopeNonStrictMode(rule));
|
||||||
|
|
||||||
|
} else if (isPresent(prevRule) &&
|
||||||
|
prevRule.selectorText == _POLYFILL_UNSCOPED_NEXT_SELECTOR) {
|
||||||
|
var content = this.extractContent(prevRule);
|
||||||
|
var r = new _Rule(content, rule.body, null);
|
||||||
|
ListWrapper.push(scopedRules, this.ruleToString(r));
|
||||||
|
|
||||||
|
} else if (isPresent(prevRule) &&
|
||||||
|
prevRule.selectorText == _POLYFILL_NEXT_SELECTOR) {
|
||||||
|
|
||||||
|
var content = this.extractContent(prevRule);
|
||||||
|
var r = new _Rule(content, rule.body, null);
|
||||||
|
ListWrapper.push(scopedRules, this.scopeStrictMode(r))
|
||||||
|
|
||||||
|
} else if (rule.selectorText != _POLYFILL_NON_STRICT &&
|
||||||
|
rule.selectorText != _POLYFILL_UNSCOPED_NEXT_SELECTOR &&
|
||||||
|
rule.selectorText != _POLYFILL_NEXT_SELECTOR) {
|
||||||
|
ListWrapper.push(scopedRules, this.scopeStrictMode(rule));
|
||||||
|
}
|
||||||
|
prevRule = rule;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ListWrapper.join(scopedRules, '\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
extractContent(rule: _Rule): string {
|
||||||
|
var match = RegExpWrapper.firstMatch(_CONTENT_RE, rule.body);
|
||||||
|
return isPresent(match) ? match[1] : '';
|
||||||
|
}
|
||||||
|
|
||||||
|
ruleToString(rule: _Rule): string {
|
||||||
|
return `${rule.selectorText} ${rule.body}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
scopeStrictMode(rule: _Rule): string {
|
||||||
|
if (rule.hasNestedRules()) {
|
||||||
|
var selector = rule.selectorText;
|
||||||
|
var rules = this.scopeRules(rule.rules);
|
||||||
|
return `${selector} {\n${rules}\n}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
var scopedSelector = this.scopeSelector(rule.selectorText, true);
|
||||||
|
var scopedBody = rule.body;
|
||||||
|
return `${scopedSelector} ${scopedBody}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
scopeNonStrictMode(rule: _Rule): string {
|
||||||
|
var scopedSelector = this.scopeSelector(rule.selectorText, false);
|
||||||
|
var scopedBody = rule.body;
|
||||||
|
return `${scopedSelector} ${scopedBody}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
scopeSelector(selector: string, strict: boolean) {
|
||||||
|
var parts = this.replaceCombinators(selector).split(',');
|
||||||
|
var scopedParts = [];
|
||||||
|
for (var i = 0; i < parts.length; i++) {
|
||||||
|
var part = parts[i];
|
||||||
|
var sel = this.scopeSimpleSelector(part.trim(), strict);
|
||||||
|
ListWrapper.push(scopedParts, sel)
|
||||||
|
}
|
||||||
|
return ListWrapper.join(scopedParts, ', ');
|
||||||
|
}
|
||||||
|
|
||||||
|
replaceCombinators(selector: string): string {
|
||||||
|
for (var i = 0; i < _COMBINATORS.length; i++) {
|
||||||
|
var combinator = _COMBINATORS[i];
|
||||||
|
selector = StringWrapper.replaceAll(selector, combinator, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
return selector;
|
||||||
|
}
|
||||||
|
|
||||||
|
scopeSimpleSelector(selector: string, strict: boolean) {
|
||||||
|
if (StringWrapper.contains(selector, _HOST_TOKEN)) {
|
||||||
|
return this.replaceColonSelectors(selector);
|
||||||
|
} else if (strict) {
|
||||||
|
return this.insertTagToEverySelectorPart(selector);
|
||||||
|
} else {
|
||||||
|
return `${this._tag} ${selector}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
replaceColonSelectors(css: string): string {
|
||||||
|
return StringWrapper.replaceAllMapped(css, _COLON_SELECTORS, (m) => {
|
||||||
|
var selectorInParens;
|
||||||
|
if (isPresent(m[2])) {
|
||||||
|
var len = selectorInParens.length;
|
||||||
|
selectorInParens = StringWrapper.substring(selectorInParens, 1, len - 1);
|
||||||
|
} else {
|
||||||
|
selectorInParens = '';
|
||||||
|
}
|
||||||
|
var rest = m[3];
|
||||||
|
return `${this._tag}${selectorInParens}${rest}`;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
insertTagToEverySelectorPart(selector: string): string {
|
||||||
|
selector = this.handleIsSelector(selector);
|
||||||
|
|
||||||
|
for (var i = 0; i < _SELECTOR_SPLITS.length; i++) {
|
||||||
|
var split = _SELECTOR_SPLITS[i];
|
||||||
|
var parts = selector.split(split);
|
||||||
|
for (var j = 0; j < parts.length; j++) {
|
||||||
|
parts[j] = this.insertAttrSuffixIntoSelectorPart(parts[j].trim());
|
||||||
|
}
|
||||||
|
selector = parts.join(split);
|
||||||
|
}
|
||||||
|
return selector;
|
||||||
|
}
|
||||||
|
|
||||||
|
insertAttrSuffixIntoSelectorPart(p: string): string {
|
||||||
|
var shouldInsert = p.length > 0 &&
|
||||||
|
!ListWrapper.contains(_SELECTOR_SPLITS, p) &&
|
||||||
|
!StringWrapper.contains(p, this._attr);
|
||||||
|
return shouldInsert ? this.insertAttr(p) : p;
|
||||||
|
}
|
||||||
|
|
||||||
|
insertAttr(selector: string): string {
|
||||||
|
return StringWrapper.replaceAllMapped(selector, _SIMPLE_SELECTORS, (m) => {
|
||||||
|
var basePart = m[1];
|
||||||
|
var colonPart = m[2];
|
||||||
|
var rest = m[3];
|
||||||
|
return (m[0].length > 0) ? `${basePart}${this._attr}${colonPart}${rest}` : '';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
handleIsSelector(selector: string) {
|
||||||
|
return StringWrapper.replaceAllMapped(selector, _IS_SELECTORS, function(m) {
|
||||||
|
return m[1];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _Token {
|
||||||
|
string: string;
|
||||||
|
type: string;
|
||||||
|
|
||||||
|
constructor(string: string, type: string) {
|
||||||
|
this.string = string;
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var _EOF_TOKEN = new _Token(null, null);
|
||||||
|
|
||||||
|
class _Lexer {
|
||||||
|
peek: int;
|
||||||
|
index: int;
|
||||||
|
input: string;
|
||||||
|
length: int;
|
||||||
|
|
||||||
|
constructor(input: string) {
|
||||||
|
this.input = input;
|
||||||
|
this.length = input.length;
|
||||||
|
this.index = -1;
|
||||||
|
this.advance();
|
||||||
|
}
|
||||||
|
|
||||||
|
parse(): List<_Token> {
|
||||||
|
var tokens = [];
|
||||||
|
var token = this.scanToken();
|
||||||
|
while (token !== _EOF_TOKEN) {
|
||||||
|
ListWrapper.push(tokens, token);
|
||||||
|
token = this.scanToken();
|
||||||
|
}
|
||||||
|
return tokens;
|
||||||
|
}
|
||||||
|
|
||||||
|
scanToken(): _Token {
|
||||||
|
this.skipWhitespace();
|
||||||
|
if (this.peek === _$EOF) return _EOF_TOKEN;
|
||||||
|
if (this.isBodyEnd(this.peek)) {
|
||||||
|
this.advance();
|
||||||
|
return new _Token('}', 'rparen');
|
||||||
|
}
|
||||||
|
if (this.isMedia(this.peek)) return this.scanMedia();
|
||||||
|
if (this.isSelector(this.peek)) return this.scanSelector();
|
||||||
|
if (this.isBodyStart(this.peek)) return this.scanBody();
|
||||||
|
|
||||||
|
return _EOF_TOKEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
isSelector(v: int): boolean {
|
||||||
|
return !this.isBodyStart(v) && v !== _$EOF;
|
||||||
|
}
|
||||||
|
|
||||||
|
isBodyStart(v: int): boolean {
|
||||||
|
return v === _$LBRACE;
|
||||||
|
}
|
||||||
|
|
||||||
|
isBodyEnd(v: int): boolean {
|
||||||
|
return v === _$RBRACE;
|
||||||
|
}
|
||||||
|
|
||||||
|
isMedia(v: int): boolean {
|
||||||
|
return v === 64; // @ -> 64
|
||||||
|
}
|
||||||
|
|
||||||
|
isWhitespace(v: int): boolean {
|
||||||
|
return (v >= _$TAB && v <= _$SPACE) || (v == _$NBSP)
|
||||||
|
}
|
||||||
|
|
||||||
|
skipWhitespace() {
|
||||||
|
while (this.isWhitespace(this.peek)) {
|
||||||
|
if (++this.index >= this.length) {
|
||||||
|
this.peek = _$EOF;
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
this.peek = StringWrapper.charCodeAt(this.input, this.index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
scanSelector(): _Token {
|
||||||
|
var start = this.index;
|
||||||
|
this.advance();
|
||||||
|
while (this.isSelector(this.peek)) {
|
||||||
|
this.advance();
|
||||||
|
}
|
||||||
|
var selector = StringWrapper.substring(this.input, start, this.index);
|
||||||
|
return new _Token(selector.trim(), 'selector');
|
||||||
|
}
|
||||||
|
|
||||||
|
scanBody(): _Token {
|
||||||
|
var start = this.index;
|
||||||
|
this.advance();
|
||||||
|
while (!this.isBodyEnd(this.peek)) {
|
||||||
|
this.advance();
|
||||||
|
}
|
||||||
|
this.advance();
|
||||||
|
var body = StringWrapper.substring(this.input, start, this.index);
|
||||||
|
return new _Token(body, 'body');
|
||||||
|
}
|
||||||
|
|
||||||
|
scanMedia(): _Token {
|
||||||
|
var start = this.index;
|
||||||
|
this.advance();
|
||||||
|
while (!this.isBodyStart(this.peek)) {
|
||||||
|
this.advance();
|
||||||
|
}
|
||||||
|
var media = StringWrapper.substring(this.input, start, this.index);
|
||||||
|
this.advance(); // skip "{"
|
||||||
|
return new _Token(media, 'media');
|
||||||
|
}
|
||||||
|
|
||||||
|
advance() {
|
||||||
|
this.index++;
|
||||||
|
if (this.index >= this.length) {
|
||||||
|
this.peek = _$EOF;
|
||||||
|
} else {
|
||||||
|
this.peek = StringWrapper.charCodeAt(this.input, this.index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _Parser {
|
||||||
|
tokens: List<_Token>;
|
||||||
|
currentIndex: int;
|
||||||
|
|
||||||
|
constructor(input: string) {
|
||||||
|
this.tokens = new _Lexer(input).parse();
|
||||||
|
this.currentIndex = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
parse(): List<_Rule> {
|
||||||
|
var rules = [];
|
||||||
|
var rule;
|
||||||
|
while (isPresent(rule = this.parseRule())) {
|
||||||
|
ListWrapper.push(rules, rule);
|
||||||
|
}
|
||||||
|
return rules;
|
||||||
|
}
|
||||||
|
|
||||||
|
parseRule(): _Rule {
|
||||||
|
try {
|
||||||
|
if (this.getNext().type === 'media') {
|
||||||
|
return this.parseMedia();
|
||||||
|
} else {
|
||||||
|
return this.parseCssRule();
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
parseMedia(): _Rule {
|
||||||
|
this.advance('media');
|
||||||
|
var media = this.getCurrent().string;
|
||||||
|
var rules = [];
|
||||||
|
while (this.getNext().type !== 'rparen') {
|
||||||
|
ListWrapper.push(rules, this.parseCssRule());
|
||||||
|
}
|
||||||
|
this.advance('rparen');
|
||||||
|
return new _Rule(media.trim(), null, rules);
|
||||||
|
}
|
||||||
|
|
||||||
|
parseCssRule() {
|
||||||
|
this.advance('selector');
|
||||||
|
var selector = this.getCurrent().string;
|
||||||
|
this.advance('body');
|
||||||
|
var body = this.getCurrent().string;
|
||||||
|
return new _Rule(selector, body, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
advance(expected: string) {
|
||||||
|
this.currentIndex++;
|
||||||
|
if (this.getCurrent().type !== expected) {
|
||||||
|
throw new BaseException(`Unexpected token "${this.getCurrent().type}". Expected "${expected}"`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getNext(): _Token {
|
||||||
|
return this.tokens[this.currentIndex + 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
getCurrent(): _Token {
|
||||||
|
return this.tokens[this.currentIndex];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class _Rule {
|
||||||
|
selectorText: string;
|
||||||
|
body: string;
|
||||||
|
rules: List<_Rule>;
|
||||||
|
|
||||||
|
constructor(selectorText: string, body: string, rules: List<_Rule>) {
|
||||||
|
this.selectorText = selectorText;
|
||||||
|
this.body = body;
|
||||||
|
this.rules = rules;
|
||||||
|
}
|
||||||
|
|
||||||
|
hasNestedRules() {
|
||||||
|
return isPresent(this.rules);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,19 +1,29 @@
|
||||||
import {CONST} from 'angular2/src/facade/lang';
|
import {Type, isBlank, isPresent} from 'angular2/src/facade/lang';
|
||||||
import {DOM, Element} from 'angular2/src/facade/dom';
|
import {DOM, Element, StyleElement} from 'angular2/src/facade/dom';
|
||||||
import {List} from 'angular2/src/facade/collection';
|
import {List, ListWrapper} from 'angular2/src/facade/collection';
|
||||||
import {View} from './view';
|
import {View} from './view';
|
||||||
import {Content} from './shadow_dom_emulation/content_tag';
|
import {Content} from './shadow_dom_emulation/content_tag';
|
||||||
import {LightDom} from './shadow_dom_emulation/light_dom';
|
import {LightDom} from './shadow_dom_emulation/light_dom';
|
||||||
|
import {DirectiveMetadata} from './directive_metadata';
|
||||||
|
import {shimCssText} from './shadow_dom_emulation/shim_css';
|
||||||
|
|
||||||
export class ShadowDomStrategy {
|
export class ShadowDomStrategy {
|
||||||
@CONST() constructor() {}
|
|
||||||
attachTemplate(el:Element, view:View){}
|
attachTemplate(el:Element, view:View){}
|
||||||
constructLightDom(lightDomView:View, shadowDomView:View, el:Element){}
|
constructLightDom(lightDomView:View, shadowDomView:View, el:Element){}
|
||||||
polyfillDirectives():List<Type>{ return null; };
|
polyfillDirectives():List<Type>{ return null; }
|
||||||
|
processTemplate(template: Element, cmpMetadata: DirectiveMetadata) { return null; }
|
||||||
}
|
}
|
||||||
|
|
||||||
export class EmulatedShadowDomStrategy extends ShadowDomStrategy {
|
export class EmulatedShadowDomStrategy extends ShadowDomStrategy {
|
||||||
@CONST() constructor() {}
|
_styleHost: Element;
|
||||||
|
|
||||||
|
constructor(styleHost: Element = null) {
|
||||||
|
if (isBlank(styleHost)) {
|
||||||
|
styleHost = DOM.defaultDoc().head;
|
||||||
|
}
|
||||||
|
this._styleHost = styleHost;
|
||||||
|
}
|
||||||
|
|
||||||
attachTemplate(el:Element, view:View){
|
attachTemplate(el:Element, view:View){
|
||||||
DOM.clearNodes(el);
|
DOM.clearNodes(el);
|
||||||
moveViewNodesIntoParent(el, view);
|
moveViewNodesIntoParent(el, view);
|
||||||
|
@ -26,10 +36,26 @@ export class EmulatedShadowDomStrategy extends ShadowDomStrategy {
|
||||||
polyfillDirectives():List<Type> {
|
polyfillDirectives():List<Type> {
|
||||||
return [Content];
|
return [Content];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
processTemplate(template: Element, cmpMetadata: DirectiveMetadata) {
|
||||||
|
var templateRoot = DOM.templateAwareRoot(template);
|
||||||
|
var attrName = cmpMetadata.annotation.selector;
|
||||||
|
|
||||||
|
// Shim CSS for emulated shadow DOM and attach the styles do the document head
|
||||||
|
var styles = _detachStyles(templateRoot);
|
||||||
|
for (var i = 0; i < styles.length; i++) {
|
||||||
|
var style = styles[i];
|
||||||
|
var processedCss = shimCssText(DOM.getText(style), attrName);
|
||||||
|
DOM.setText(style, processedCss);
|
||||||
|
}
|
||||||
|
_attachStyles(this._styleHost, styles);
|
||||||
|
|
||||||
|
// Update the DOM to trigger the CSS
|
||||||
|
_addAttributeToChildren(templateRoot, attrName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class NativeShadowDomStrategy extends ShadowDomStrategy {
|
export class NativeShadowDomStrategy extends ShadowDomStrategy {
|
||||||
@CONST() constructor() {}
|
|
||||||
attachTemplate(el:Element, view:View){
|
attachTemplate(el:Element, view:View){
|
||||||
moveViewNodesIntoParent(el.createShadowRoot(), view);
|
moveViewNodesIntoParent(el.createShadowRoot(), view);
|
||||||
}
|
}
|
||||||
|
@ -41,6 +67,10 @@ export class NativeShadowDomStrategy extends ShadowDomStrategy {
|
||||||
polyfillDirectives():List<Type> {
|
polyfillDirectives():List<Type> {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
processTemplate(template: Element, cmpMetadata: DirectiveMetadata) {
|
||||||
|
return template;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function moveViewNodesIntoParent(parent, view) {
|
function moveViewNodesIntoParent(parent, view) {
|
||||||
|
@ -48,3 +78,38 @@ function moveViewNodesIntoParent(parent, view) {
|
||||||
DOM.appendChild(parent, view.nodes[i]);
|
DOM.appendChild(parent, view.nodes[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(vicb): union types: el is an Element or a Document Fragment
|
||||||
|
function _detachStyles(el): List<StyleElement> {
|
||||||
|
var nodeList = DOM.querySelectorAll(el, 'style');
|
||||||
|
var styles = [];
|
||||||
|
for (var i = 0; i < nodeList.length; i++) {
|
||||||
|
var style = DOM.remove(nodeList[i]);
|
||||||
|
ListWrapper.push(styles, style);
|
||||||
|
}
|
||||||
|
return styles;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move the styles as the first children of the template
|
||||||
|
function _attachStyles(el: Element, styles: List<StyleElement>) {
|
||||||
|
var firstChild = DOM.firstChild(el);
|
||||||
|
for (var i = styles.length - 1; i >= 0; i--) {
|
||||||
|
var style = styles[i];
|
||||||
|
if (isPresent(firstChild)) {
|
||||||
|
DOM.insertBefore(firstChild, style);
|
||||||
|
} else {
|
||||||
|
DOM.appendChild(el, style);
|
||||||
|
}
|
||||||
|
firstChild = style;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(vicb): union types: el is an Element or a Document Fragment
|
||||||
|
function _addAttributeToChildren(el, attrName:string) {
|
||||||
|
// TODO(vicb): currently the code crashes when the attrName is not an el selector
|
||||||
|
var children = DOM.querySelectorAll(el, "*");
|
||||||
|
for (var i = 0; i < children.length; i++) {
|
||||||
|
var child = children[i];
|
||||||
|
DOM.setAttribute(child, attrName, '');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,11 +1,51 @@
|
||||||
import {Promise} from 'angular2/src/facade/async';
|
import {Promise, PromiseWrapper} from 'angular2/src/facade/async';
|
||||||
//import {Document} from 'angular2/src/facade/dom';
|
import {isBlank, isPresent, BaseException, stringify} from 'angular2/src/facade/lang';
|
||||||
|
import {TemplateElement, DOM} from 'angular2/src/facade/dom';
|
||||||
|
import {StringMapWrapper} from 'angular2/src/facade/collection';
|
||||||
|
|
||||||
|
import {TemplateConfig} from 'angular2/src/core/annotations/template_config';
|
||||||
|
import {Component} from 'angular2/src/core/annotations/annotations';
|
||||||
|
|
||||||
|
import {DirectiveMetadata} from 'angular2/src/core/compiler/directive_metadata';
|
||||||
|
|
||||||
|
import {XHR} from './xhr/xhr';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Strategy to load component templates.
|
* Strategy to load component templates.
|
||||||
*/
|
*/
|
||||||
export class TemplateLoader {
|
export class TemplateLoader {
|
||||||
load(url:string):Promise<Document> {
|
_xhr: XHR;
|
||||||
return null;
|
_cache;
|
||||||
|
|
||||||
|
constructor(xhr: XHR) {
|
||||||
|
this._xhr = xhr;
|
||||||
|
this._cache = StringMapWrapper.create();
|
||||||
|
}
|
||||||
|
|
||||||
|
load(cmpMetadata: DirectiveMetadata):Promise<Element> {
|
||||||
|
var annotation:Component = cmpMetadata.annotation;
|
||||||
|
var tplConfig:TemplateConfig = annotation.template;
|
||||||
|
|
||||||
|
if (isPresent(tplConfig.inline)) {
|
||||||
|
var template = DOM.createTemplate(tplConfig.inline);
|
||||||
|
return PromiseWrapper.resolve(template);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isPresent(tplConfig.url)) {
|
||||||
|
var url = tplConfig.url;
|
||||||
|
var promise = StringMapWrapper.get(this._cache, url);
|
||||||
|
|
||||||
|
if (isBlank(promise)) {
|
||||||
|
promise = this._xhr.get(url).then(function (html) {
|
||||||
|
var template = DOM.createTemplate(html);
|
||||||
|
return template;
|
||||||
|
});
|
||||||
|
StringMapWrapper.set(this._cache, url, promise);
|
||||||
|
}
|
||||||
|
|
||||||
|
return promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new BaseException(`No template configured for component ${stringify(cmpMetadata.type)}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -15,6 +15,7 @@ import {ViewPort} from './viewport';
|
||||||
import {OnChange} from './interfaces';
|
import {OnChange} from './interfaces';
|
||||||
import {Content} from './shadow_dom_emulation/content_tag';
|
import {Content} from './shadow_dom_emulation/content_tag';
|
||||||
import {LightDom, DestinationLightDom} from './shadow_dom_emulation/light_dom';
|
import {LightDom, DestinationLightDom} from './shadow_dom_emulation/light_dom';
|
||||||
|
import {ShadowDomStrategy} from './shadow_dom_strategy';
|
||||||
|
|
||||||
const NG_BINDING_CLASS = 'ng-binding';
|
const NG_BINDING_CLASS = 'ng-binding';
|
||||||
const NG_BINDING_CLASS_SELECTOR = '.ng-binding';
|
const NG_BINDING_CLASS_SELECTOR = '.ng-binding';
|
||||||
|
@ -256,9 +257,11 @@ export class ProtoView {
|
||||||
instantiateInPlace:boolean;
|
instantiateInPlace:boolean;
|
||||||
rootBindingOffset:int;
|
rootBindingOffset:int;
|
||||||
isTemplateElement:boolean;
|
isTemplateElement:boolean;
|
||||||
|
shadowDomStrategy: ShadowDomStrategy;
|
||||||
constructor(
|
constructor(
|
||||||
template:Element,
|
template:Element,
|
||||||
protoChangeDetector:ProtoChangeDetector) {
|
protoChangeDetector:ProtoChangeDetector,
|
||||||
|
shadowDomStrategy: ShadowDomStrategy) {
|
||||||
this.element = template;
|
this.element = template;
|
||||||
this.elementBinders = [];
|
this.elementBinders = [];
|
||||||
this.variableBindings = MapWrapper.create();
|
this.variableBindings = MapWrapper.create();
|
||||||
|
@ -270,6 +273,7 @@ export class ProtoView {
|
||||||
this.rootBindingOffset = (isPresent(this.element) && DOM.hasClass(this.element, NG_BINDING_CLASS))
|
this.rootBindingOffset = (isPresent(this.element) && DOM.hasClass(this.element, NG_BINDING_CLASS))
|
||||||
? 1 : 0;
|
? 1 : 0;
|
||||||
this.isTemplateElement = this.element instanceof TemplateElement;
|
this.isTemplateElement = this.element instanceof TemplateElement;
|
||||||
|
this.shadowDomStrategy = shadowDomStrategy;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(rado): hostElementInjector should be moved to hydrate phase.
|
// TODO(rado): hostElementInjector should be moved to hydrate phase.
|
||||||
|
@ -353,11 +357,12 @@ export class ProtoView {
|
||||||
var lightDom = null;
|
var lightDom = null;
|
||||||
var bindingPropagationConfig = null;
|
var bindingPropagationConfig = null;
|
||||||
if (isPresent(binder.componentDirective)) {
|
if (isPresent(binder.componentDirective)) {
|
||||||
|
var strategy = this.shadowDomStrategy;
|
||||||
var childView = binder.nestedProtoView.instantiate(elementInjector);
|
var childView = binder.nestedProtoView.instantiate(elementInjector);
|
||||||
view.changeDetector.addChild(childView.changeDetector);
|
view.changeDetector.addChild(childView.changeDetector);
|
||||||
|
|
||||||
lightDom = binder.componentDirective.shadowDomStrategy.constructLightDom(view, childView, element);
|
lightDom = strategy.constructLightDom(view, childView, element);
|
||||||
binder.componentDirective.shadowDomStrategy.attachTemplate(element, childView);
|
strategy.attachTemplate(element, childView);
|
||||||
|
|
||||||
bindingPropagationConfig = new BindingPropagationConfig(view.changeDetector);
|
bindingPropagationConfig = new BindingPropagationConfig(view.changeDetector);
|
||||||
|
|
||||||
|
@ -497,12 +502,14 @@ 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: DirectiveMetadata,
|
insertionElement,
|
||||||
protoChangeDetector:ProtoChangeDetector
|
rootComponentAnnotatedType: DirectiveMetadata,
|
||||||
|
protoChangeDetector:ProtoChangeDetector,
|
||||||
|
shadowDomStrategy: ShadowDomStrategy
|
||||||
): ProtoView {
|
): ProtoView {
|
||||||
|
|
||||||
DOM.addClass(insertionElement, 'ng-binding');
|
DOM.addClass(insertionElement, 'ng-binding');
|
||||||
var rootProtoView = new ProtoView(insertionElement, protoChangeDetector);
|
var rootProtoView = new ProtoView(insertionElement, protoChangeDetector, shadowDomStrategy);
|
||||||
rootProtoView.instantiateInPlace = true;
|
rootProtoView.instantiateInPlace = true;
|
||||||
var binder = rootProtoView.bindElement(
|
var binder = rootProtoView.bindElement(
|
||||||
new ProtoElementInjector(null, 0, [rootComponentAnnotatedType.type], true));
|
new ProtoElementInjector(null, 0, [rootComponentAnnotatedType.type], true));
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
import {Promise} from 'angular2/src/facade/async';
|
||||||
|
|
||||||
|
export class XHR {
|
||||||
|
get(url: string): Promise<string> {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
import 'dart:async';
|
||||||
|
import 'dart:html';
|
||||||
|
import './xhr.dart' show XHR;
|
||||||
|
|
||||||
|
class XHRImpl extends XHR {
|
||||||
|
Future<String> get(String url) {
|
||||||
|
return HttpRequest.request(url).then(
|
||||||
|
(HttpRequest request) => request.responseText,
|
||||||
|
onError: (Error e) => throw 'Failed to load $url'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
import {Promise, PromiseWrapper} from 'angular2/src/facade/async';
|
||||||
|
import {XHR} from './xhr';
|
||||||
|
|
||||||
|
export class XHRImpl extends XHR {
|
||||||
|
get(url: string): Promise<string> {
|
||||||
|
var completer = PromiseWrapper.completer();
|
||||||
|
var xhr = new XMLHttpRequest();
|
||||||
|
xhr.open('GET', url, true);
|
||||||
|
xhr.responseType = 'text';
|
||||||
|
|
||||||
|
xhr.onload = function() {
|
||||||
|
var status = xhr.status;
|
||||||
|
if (200 <= status && status <= 300) {
|
||||||
|
completer.complete(xhr.responseText);
|
||||||
|
} else {
|
||||||
|
completer.reject(`Failed to load ${url}`);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
xhr.onerror = function() {
|
||||||
|
completer.reject(`Failed to load ${url}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
xhr.send();
|
||||||
|
return completer.promise;
|
||||||
|
}
|
||||||
|
}
|
|
@ -104,9 +104,7 @@ class ListWrapper {
|
||||||
static void insert(List l, int index, value) {
|
static void insert(List l, int index, value) {
|
||||||
l.insert(index, value);
|
l.insert(index, value);
|
||||||
}
|
}
|
||||||
static void removeAt(List l, int index) {
|
static removeAt(List l, int index) => l.removeAt(index);
|
||||||
l.removeAt(index);
|
|
||||||
}
|
|
||||||
static void removeAll(List list, List items) {
|
static void removeAll(List list, List items) {
|
||||||
for (var i = 0; i < items.length; ++i) {
|
for (var i = 0; i < items.length; ++i) {
|
||||||
list.remove(items[i]);
|
list.remove(items[i]);
|
||||||
|
|
|
@ -3,7 +3,16 @@ library angular.core.facade.dom;
|
||||||
import 'dart:html';
|
import 'dart:html';
|
||||||
import 'dart:js' show JsObject, context;
|
import 'dart:js' show JsObject, context;
|
||||||
|
|
||||||
export 'dart:html' show DocumentFragment, Node, Element, TemplateElement, Text, document, location, window;
|
export 'dart:html' show
|
||||||
|
document,
|
||||||
|
DocumentFragment,
|
||||||
|
Element,
|
||||||
|
location,
|
||||||
|
Node,
|
||||||
|
StyleElement,
|
||||||
|
TemplateElement,
|
||||||
|
Text,
|
||||||
|
window;
|
||||||
|
|
||||||
// TODO(tbosch): Is there a builtin one? Why is Dart
|
// TODO(tbosch): Is there a builtin one? Why is Dart
|
||||||
// removing unknown elements by default?
|
// removing unknown elements by default?
|
||||||
|
@ -62,7 +71,10 @@ class DOM {
|
||||||
static void removeChild(Element el, Node node) {
|
static void removeChild(Element el, Node node) {
|
||||||
node.remove();
|
node.remove();
|
||||||
}
|
}
|
||||||
static void insertBefore(Node el, Node node) {
|
static Element remove(Element el) {
|
||||||
|
return el..remove();
|
||||||
|
}
|
||||||
|
static insertBefore(Node el, node) {
|
||||||
el.parentNode.insertBefore(node, el);
|
el.parentNode.insertBefore(node, el);
|
||||||
}
|
}
|
||||||
static void insertAllBefore(Node el, Iterable<Node> nodes) {
|
static void insertAllBefore(Node el, Iterable<Node> nodes) {
|
||||||
|
@ -72,8 +84,8 @@ class DOM {
|
||||||
el.parentNode.insertBefore(node, el.nextNode);
|
el.parentNode.insertBefore(node, el.nextNode);
|
||||||
}
|
}
|
||||||
static String getText(Node el) => el.text;
|
static String getText(Node el) => el.text;
|
||||||
static void setText(Text text, String value) {
|
static void setText(Node el, String value) {
|
||||||
text.text = value;
|
el.text = value;
|
||||||
}
|
}
|
||||||
static TemplateElement createTemplate(String html) {
|
static TemplateElement createTemplate(String html) {
|
||||||
var t = new TemplateElement();
|
var t = new TemplateElement();
|
||||||
|
@ -116,6 +128,10 @@ class DOM {
|
||||||
static String getAttribute(Element element, String attribute) =>
|
static String getAttribute(Element element, String attribute) =>
|
||||||
element.getAttribute(attribute);
|
element.getAttribute(attribute);
|
||||||
|
|
||||||
|
static void setAttribute(Element element, String name, String value) {
|
||||||
|
element.setAttribute(name, value);
|
||||||
|
}
|
||||||
|
|
||||||
static Node templateAwareRoot(Element el) =>
|
static Node templateAwareRoot(Element el) =>
|
||||||
el is TemplateElement ? el.content : el;
|
el is TemplateElement ? el.content : el;
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ export var NodeList = window.NodeList;
|
||||||
export var Text = window.Text;
|
export var Text = window.Text;
|
||||||
export var Element = window.HTMLElement;
|
export var Element = window.HTMLElement;
|
||||||
export var TemplateElement = window.HTMLTemplateElement;
|
export var TemplateElement = window.HTMLTemplateElement;
|
||||||
|
export var StyleElement = window.HTMLStyleElement;
|
||||||
export var document = window.document;
|
export var document = window.document;
|
||||||
export var location = window.location;
|
export var location = window.location;
|
||||||
export var gc = window.gc ? () => window.gc() : () => null;
|
export var gc = window.gc ? () => window.gc() : () => null;
|
||||||
|
@ -70,6 +71,11 @@ export class DOM {
|
||||||
static removeChild(el, node) {
|
static removeChild(el, node) {
|
||||||
el.removeChild(node);
|
el.removeChild(node);
|
||||||
}
|
}
|
||||||
|
static remove(el: Element): Element {
|
||||||
|
var parent = el.parentNode;
|
||||||
|
parent.removeChild(el);
|
||||||
|
return el;
|
||||||
|
}
|
||||||
static insertBefore(el, node) {
|
static insertBefore(el, node) {
|
||||||
el.parentNode.insertBefore(node, el);
|
el.parentNode.insertBefore(node, el);
|
||||||
}
|
}
|
||||||
|
@ -87,8 +93,9 @@ export class DOM {
|
||||||
static getText(el: Element) {
|
static getText(el: Element) {
|
||||||
return el.textContent;
|
return el.textContent;
|
||||||
}
|
}
|
||||||
static setText(text:Text, value:string) {
|
// TODO(vicb): removed Element type because it does not support StyleElement
|
||||||
text.nodeValue = value;
|
static setText(el, value:string) {
|
||||||
|
el.textContent = value;
|
||||||
}
|
}
|
||||||
static createTemplate(html) {
|
static createTemplate(html) {
|
||||||
var t = document.createElement('template');
|
var t = document.createElement('template');
|
||||||
|
@ -103,6 +110,11 @@ export class DOM {
|
||||||
el.setAttribute(attrName, attrValue);
|
el.setAttribute(attrName, attrValue);
|
||||||
return el;
|
return el;
|
||||||
}
|
}
|
||||||
|
static createStyleElement(css:string, doc=document):StyleElement {
|
||||||
|
var style = doc.createElement('STYLE');
|
||||||
|
style.innerText = css;
|
||||||
|
return style;
|
||||||
|
}
|
||||||
static clone(node:Node) {
|
static clone(node:Node) {
|
||||||
return node.cloneNode(true);
|
return node.cloneNode(true);
|
||||||
}
|
}
|
||||||
|
@ -142,6 +154,9 @@ export class DOM {
|
||||||
static getAttribute(element:Element, attribute:string) {
|
static getAttribute(element:Element, attribute:string) {
|
||||||
return element.getAttribute(attribute);
|
return element.getAttribute(attribute);
|
||||||
}
|
}
|
||||||
|
static setAttribute(element:Element, name:string, value:string) {
|
||||||
|
element.setAttribute(name, value);
|
||||||
|
}
|
||||||
static templateAwareRoot(el:Element):Node {
|
static templateAwareRoot(el:Element):Node {
|
||||||
return el instanceof TemplateElement ? el.content : el;
|
return el instanceof TemplateElement ? el.content : el;
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,6 +69,14 @@ class StringWrapper {
|
||||||
static String substring(String s, int start, [int end]) {
|
static String substring(String s, int start, [int end]) {
|
||||||
return s.substring(start, end);
|
return s.substring(start, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static String replaceAllMapped(String s, RegExp from, Function cb) {
|
||||||
|
return s.replaceAllMapped(from, cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool contains(String s, String substr) {
|
||||||
|
return s.contains(substr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class StringJoiner {
|
class StringJoiner {
|
||||||
|
@ -102,8 +110,10 @@ class NumberWrapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
class RegExpWrapper {
|
class RegExpWrapper {
|
||||||
static RegExp create(String regExpStr) {
|
static RegExp create(regExpStr, [String flags = '']) {
|
||||||
return new RegExp(regExpStr);
|
bool multiLine = flags.contains('m');
|
||||||
|
bool caseSensitive = !flags.contains('i');
|
||||||
|
return new RegExp(regExpStr, multiLine: multiLine, caseSensitive: caseSensitive);
|
||||||
}
|
}
|
||||||
static Match firstMatch(RegExp regExp, String input) {
|
static Match firstMatch(RegExp regExp, String input) {
|
||||||
return regExp.firstMatch(input);
|
return regExp.firstMatch(input);
|
||||||
|
|
|
@ -75,6 +75,16 @@ export class StringWrapper {
|
||||||
static substring(s:string, start:int, end:int = undefined) {
|
static substring(s:string, start:int, end:int = undefined) {
|
||||||
return s.substring(start, end);
|
return s.substring(start, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static replaceAllMapped(s:string, from:RegExp, cb:Function): string {
|
||||||
|
return s.replace(from.multiple, function(...matches) {
|
||||||
|
return cb(matches);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static contains(s:string, substr:string): boolean {
|
||||||
|
return s.indexOf(substr) != -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class StringJoiner {
|
export class StringJoiner {
|
||||||
|
@ -160,10 +170,11 @@ export var RegExp = assert.define('RegExp', function(obj) {
|
||||||
});
|
});
|
||||||
|
|
||||||
export class RegExpWrapper {
|
export class RegExpWrapper {
|
||||||
static create(regExpStr):RegExp {
|
static create(regExpStr, flags:string = ''):RegExp {
|
||||||
|
flags = flags.replace(/g/g, '');
|
||||||
return {
|
return {
|
||||||
multiple: new window.RegExp(regExpStr, 'g'),
|
multiple: new window.RegExp(regExpStr, flags + 'g'),
|
||||||
single: new window.RegExp(regExpStr)
|
single: new window.RegExp(regExpStr, flags)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
static firstMatch(regExp, input) {
|
static firstMatch(regExp, input) {
|
||||||
|
|
|
@ -0,0 +1,108 @@
|
||||||
|
import {XHR} from 'angular2/src/core/compiler/xhr/xhr';
|
||||||
|
import {List, ListWrapper, Map, MapWrapper} from 'angular2/src/facade/collection';
|
||||||
|
import {isBlank, isPresent, normalizeBlank, BaseException} from 'angular2/src/facade/lang';
|
||||||
|
import {PromiseWrapper, Promise} from 'angular2/src/facade/async';
|
||||||
|
|
||||||
|
export class XHRMock extends XHR {
|
||||||
|
_expectations: List<_Expectation>;
|
||||||
|
_definitions: Map;
|
||||||
|
_requests: List<Promise>;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this._expectations = [];
|
||||||
|
this._definitions = MapWrapper.create();
|
||||||
|
this._requests = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
get(url: string): Promise<string> {
|
||||||
|
var request = new _PendingRequest(url);
|
||||||
|
ListWrapper.push(this._requests, request);
|
||||||
|
return request.getPromise();
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(url: string, response: string) {
|
||||||
|
var expectation = new _Expectation(url, response);
|
||||||
|
ListWrapper.push(this._expectations, expectation);
|
||||||
|
}
|
||||||
|
|
||||||
|
when(url: string, response: string) {
|
||||||
|
MapWrapper.set(this._definitions, url, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
flush() {
|
||||||
|
if (this._requests.length === 0) {
|
||||||
|
throw new BaseException('No pending requests to flush');
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
var request = ListWrapper.removeAt(this._requests, 0);
|
||||||
|
this._processRequest(request);
|
||||||
|
} while (this._requests.length > 0);
|
||||||
|
|
||||||
|
this.verifyNoOustandingExpectations();
|
||||||
|
}
|
||||||
|
|
||||||
|
verifyNoOustandingExpectations() {
|
||||||
|
if (this._expectations.length === 0) return;
|
||||||
|
|
||||||
|
var urls = [];
|
||||||
|
for (var i = 0; i < this._expectations.length; i++) {
|
||||||
|
var expectation = this._expectations[i];
|
||||||
|
ListWrapper.push(urls, expectation.url);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new BaseException(`Unsatisfied requests: ${ListWrapper.join(urls, ', ')}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
_processRequest(request: _PendingRequest) {
|
||||||
|
var url = request.url;
|
||||||
|
|
||||||
|
if (this._expectations.length > 0) {
|
||||||
|
var expectation = this._expectations[0];
|
||||||
|
if (expectation.url === url) {
|
||||||
|
ListWrapper.remove(this._expectations, expectation);
|
||||||
|
request.complete(expectation.response);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MapWrapper.contains(this._definitions, url)) {
|
||||||
|
var response = MapWrapper.get(this._definitions, url);
|
||||||
|
request.complete(normalizeBlank(response));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new BaseException(`Unexpected request ${url}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _PendingRequest {
|
||||||
|
url: string;
|
||||||
|
completer;
|
||||||
|
|
||||||
|
constructor(url) {
|
||||||
|
this.url = url;
|
||||||
|
this.completer = PromiseWrapper.completer();
|
||||||
|
}
|
||||||
|
|
||||||
|
complete(response: string) {
|
||||||
|
if (isBlank(response)) {
|
||||||
|
this.completer.reject(`Failed to load ${this.url}`);
|
||||||
|
} else {
|
||||||
|
this.completer.complete(response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getPromise(): Promise<string> {
|
||||||
|
return this.completer.promise;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _Expectation {
|
||||||
|
url: string;
|
||||||
|
response: string;
|
||||||
|
constructor(url: string, response: string) {
|
||||||
|
this.url = url;
|
||||||
|
this.response = response;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,18 +1,23 @@
|
||||||
import {describe, beforeEach, it, expect, ddescribe, iit, el} from 'angular2/test_lib';
|
import {describe, beforeEach, it, expect, ddescribe, iit, el, IS_DARTIUM} from 'angular2/test_lib';
|
||||||
import {DOM} from 'angular2/src/facade/dom';
|
import {DOM, Element, TemplateElement} from 'angular2/src/facade/dom';
|
||||||
import {List} from 'angular2/src/facade/collection';
|
import {List, ListWrapper, Map, MapWrapper} from 'angular2/src/facade/collection';
|
||||||
|
import {Type, isBlank} from 'angular2/src/facade/lang';
|
||||||
|
import {PromiseWrapper} from 'angular2/src/facade/async';
|
||||||
|
|
||||||
import {Compiler, CompilerCache} from 'angular2/src/core/compiler/compiler';
|
import {Compiler, CompilerCache} from 'angular2/src/core/compiler/compiler';
|
||||||
import {ProtoView} from 'angular2/src/core/compiler/view';
|
import {ProtoView} from 'angular2/src/core/compiler/view';
|
||||||
import {DirectiveMetadataReader} from 'angular2/src/core/compiler/directive_metadata_reader';
|
import {DirectiveMetadataReader} from 'angular2/src/core/compiler/directive_metadata_reader';
|
||||||
import {TemplateLoader} from 'angular2/src/core/compiler/template_loader';
|
import {DirectiveMetadata} from 'angular2/src/core/compiler/directive_metadata';
|
||||||
import {Component} from 'angular2/src/core/annotations/annotations';
|
import {Component} from 'angular2/src/core/annotations/annotations';
|
||||||
import {TemplateConfig} from 'angular2/src/core/annotations/template_config';
|
import {TemplateConfig} from 'angular2/src/core/annotations/template_config';
|
||||||
import {CompileElement} from 'angular2/src/core/compiler/pipeline/compile_element';
|
import {CompileElement} from 'angular2/src/core/compiler/pipeline/compile_element';
|
||||||
import {CompileStep} from 'angular2/src/core/compiler/pipeline/compile_step'
|
import {CompileStep} from 'angular2/src/core/compiler/pipeline/compile_step'
|
||||||
import {CompileControl} from 'angular2/src/core/compiler/pipeline/compile_control';
|
import {CompileControl} from 'angular2/src/core/compiler/pipeline/compile_control';
|
||||||
|
import {TemplateLoader} from 'angular2/src/core/compiler/template_loader';
|
||||||
|
|
||||||
import {Lexer, Parser, dynamicChangeDetection} from 'angular2/change_detection';
|
import {Lexer, Parser, dynamicChangeDetection} from 'angular2/change_detection';
|
||||||
|
import {ShadowDomStrategy, NativeShadowDomStrategy} from 'angular2/src/core/compiler/shadow_dom_strategy';
|
||||||
|
import {XHRMock} from 'angular2/src/mock/xhr_mock';
|
||||||
|
|
||||||
export function main() {
|
export function main() {
|
||||||
describe('compiler', function() {
|
describe('compiler', function() {
|
||||||
|
@ -22,13 +27,19 @@ export function main() {
|
||||||
reader = new DirectiveMetadataReader();
|
reader = new DirectiveMetadataReader();
|
||||||
});
|
});
|
||||||
|
|
||||||
function createCompiler(processClosure) {
|
function createCompiler(processClosure, strategy:ShadowDomStrategy = null, xhr: XHRMock = null) {
|
||||||
var steps = [new MockStep(processClosure)];
|
var steps = [new MockStep(processClosure)];
|
||||||
return new TestableCompiler(reader, steps);
|
if (isBlank(strategy)) {
|
||||||
|
strategy = new NativeShadowDomStrategy();
|
||||||
|
}
|
||||||
|
if (isBlank(xhr)) {
|
||||||
|
xhr = new XHRMock();
|
||||||
|
}
|
||||||
|
return new TestableCompiler(reader, steps, strategy, xhr);
|
||||||
}
|
}
|
||||||
|
|
||||||
it('should run the steps and return the ProtoView of the root element', (done) => {
|
it('should run the steps and return the ProtoView of the root element', (done) => {
|
||||||
var rootProtoView = new ProtoView(null, null);
|
var rootProtoView = new ProtoView(null, null, null);
|
||||||
var compiler = createCompiler( (parent, current, control) => {
|
var compiler = createCompiler( (parent, current, control) => {
|
||||||
current.inheritedProtoView = rootProtoView;
|
current.inheritedProtoView = rootProtoView;
|
||||||
});
|
});
|
||||||
|
@ -41,7 +52,7 @@ export function main() {
|
||||||
it('should use the given element', (done) => {
|
it('should use the given element', (done) => {
|
||||||
var element = el('<div></div>');
|
var element = el('<div></div>');
|
||||||
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, null);
|
||||||
});
|
});
|
||||||
compiler.compile(MainComponent, element).then( (protoView) => {
|
compiler.compile(MainComponent, element).then( (protoView) => {
|
||||||
expect(protoView.element).toBe(element);
|
expect(protoView.element).toBe(element);
|
||||||
|
@ -51,7 +62,7 @@ export function main() {
|
||||||
|
|
||||||
it('should use the inline template if no element is given explicitly', (done) => {
|
it('should use the inline template if no element is given explicitly', (done) => {
|
||||||
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, null);
|
||||||
});
|
});
|
||||||
compiler.compile(MainComponent, null).then( (protoView) => {
|
compiler.compile(MainComponent, null).then( (protoView) => {
|
||||||
expect(DOM.getInnerHTML(protoView.element)).toEqual('inline component');
|
expect(DOM.getInnerHTML(protoView.element)).toEqual('inline component');
|
||||||
|
@ -59,10 +70,27 @@ export function main() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should use the shadow dom strategy to process the template', (done) => {
|
||||||
|
// TODO(vicb) test in Dart when the bug is fixed
|
||||||
|
// https://code.google.com/p/dart/issues/detail?id=18249
|
||||||
|
if (IS_DARTIUM) {
|
||||||
|
done();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var templateHtml = 'processed template';
|
||||||
|
var compiler = createCompiler((parent, current, control) => {
|
||||||
|
current.inheritedProtoView = new ProtoView(current.element, null, null);
|
||||||
|
}, new FakeShadowDomStrategy(templateHtml));
|
||||||
|
compiler.compile(MainComponent, null).then( (protoView) => {
|
||||||
|
expect(DOM.getInnerHTML(protoView.element)).toEqual('processed template');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should load nested components', (done) => {
|
it('should load nested components', (done) => {
|
||||||
var mainEl = el('<div></div>');
|
var mainEl = el('<div></div>');
|
||||||
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, null);
|
||||||
current.inheritedElementBinder = current.inheritedProtoView.bindElement(null);
|
current.inheritedElementBinder = current.inheritedProtoView.bindElement(null);
|
||||||
if (current.element === mainEl) {
|
if (current.element === mainEl) {
|
||||||
current.componentDirective = reader.read(NestedComponent);
|
current.componentDirective = reader.read(NestedComponent);
|
||||||
|
@ -73,13 +101,12 @@ export function main() {
|
||||||
expect(DOM.getInnerHTML(nestedView.element)).toEqual('nested component');
|
expect(DOM.getInnerHTML(nestedView.element)).toEqual('nested component');
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should cache components', (done) => {
|
it('should cache compiled components', (done) => {
|
||||||
var element = el('<div></div>');
|
var element = el('<div></div>');
|
||||||
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, null);
|
||||||
});
|
});
|
||||||
var firstProtoView;
|
var firstProtoView;
|
||||||
compiler.compile(MainComponent, element).then( (protoView) => {
|
compiler.compile(MainComponent, element).then( (protoView) => {
|
||||||
|
@ -89,12 +116,28 @@ export function main() {
|
||||||
expect(firstProtoView).toBe(protoView);
|
expect(firstProtoView).toBe(protoView);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should re-use components being compiled', (done) => {
|
||||||
|
var nestedElBinders = [];
|
||||||
|
var mainEl = el('<div><div class="nested"></div><div class="nested"></div></div>');
|
||||||
|
var compiler = createCompiler( (parent, current, control) => {
|
||||||
|
if (DOM.hasClass(current.element, 'nested')) {
|
||||||
|
current.inheritedProtoView = new ProtoView(current.element, null, null);
|
||||||
|
current.inheritedElementBinder = current.inheritedProtoView.bindElement(null);
|
||||||
|
current.componentDirective = reader.read(NestedComponent);
|
||||||
|
ListWrapper.push(nestedElBinders, current.inheritedElementBinder);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
compiler.compile(MainComponent, mainEl).then( (protoView) => {
|
||||||
|
expect(nestedElBinders[0].nestedProtoView).toBe(nestedElBinders[1].nestedProtoView);
|
||||||
|
done();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should allow recursive components', (done) => {
|
it('should allow recursive components', (done) => {
|
||||||
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, null);
|
||||||
current.inheritedElementBinder = current.inheritedProtoView.bindElement(null);
|
current.inheritedElementBinder = current.inheritedProtoView.bindElement(null);
|
||||||
current.componentDirective = reader.read(RecursiveComponent);
|
current.componentDirective = reader.read(RecursiveComponent);
|
||||||
});
|
});
|
||||||
|
@ -102,13 +145,54 @@ export function main() {
|
||||||
expect(protoView.elementBinders[0].nestedProtoView).toBe(protoView);
|
expect(protoView.elementBinders[0].nestedProtoView).toBe(protoView);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('XHR', () => {
|
||||||
|
it('should load template via xhr', (done) => {
|
||||||
|
var xhr = new XHRMock();
|
||||||
|
xhr.expect('/parent', 'xhr');
|
||||||
|
|
||||||
|
var compiler = createCompiler((parent, current, control) => {
|
||||||
|
current.inheritedProtoView = new ProtoView(current.element, null, null);
|
||||||
|
}, null, xhr);
|
||||||
|
|
||||||
|
compiler.compile(XHRParentComponent).then( (protoView) => {
|
||||||
|
expect(DOM.getInnerHTML(protoView.element)).toEqual('xhr');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
xhr.flush();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return a rejected promise when loading a template fails', (done) => {
|
||||||
|
var xhr = new XHRMock();
|
||||||
|
xhr.expect('/parent', null);
|
||||||
|
|
||||||
|
var compiler = createCompiler((parent, current, control) => {}, null, xhr);
|
||||||
|
|
||||||
|
PromiseWrapper.then(compiler.compile(XHRParentComponent),
|
||||||
|
function(_) { throw 'Failure expected'; },
|
||||||
|
function(e) {
|
||||||
|
expect(e.message).toEqual('Failed to load the template for XHRParentComponent');
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
xhr.flush();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
template: new TemplateConfig({
|
||||||
|
url: '/parent'
|
||||||
|
})
|
||||||
|
})
|
||||||
|
class XHRParentComponent {}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
template: new TemplateConfig({
|
template: new TemplateConfig({
|
||||||
inline: 'inline component'
|
inline: 'inline component'
|
||||||
|
@ -133,10 +217,18 @@ class RecursiveComponent {}
|
||||||
|
|
||||||
class TestableCompiler extends Compiler {
|
class TestableCompiler extends Compiler {
|
||||||
steps:List;
|
steps:List;
|
||||||
constructor(reader:DirectiveMetadataReader, steps:List<CompileStep>) {
|
|
||||||
super(dynamicChangeDetection, null, reader, new Parser(new Lexer()), new CompilerCache());
|
constructor(reader:DirectiveMetadataReader, steps:List<CompileStep>, strategy:ShadowDomStrategy,
|
||||||
|
xhr: XHRMock) {
|
||||||
|
super(dynamicChangeDetection,
|
||||||
|
new TemplateLoader(xhr),
|
||||||
|
reader,
|
||||||
|
new Parser(new Lexer()),
|
||||||
|
new CompilerCache(),
|
||||||
|
strategy);
|
||||||
this.steps = steps;
|
this.steps = steps;
|
||||||
}
|
}
|
||||||
|
|
||||||
createSteps(component):List<CompileStep> {
|
createSteps(component):List<CompileStep> {
|
||||||
return this.steps;
|
return this.steps;
|
||||||
}
|
}
|
||||||
|
@ -151,3 +243,14 @@ class MockStep extends CompileStep {
|
||||||
this.processClosure(parent, current, control);
|
this.processClosure(parent, current, control);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class FakeShadowDomStrategy extends NativeShadowDomStrategy {
|
||||||
|
templateHtml: string;
|
||||||
|
constructor(templateHtml: string) {
|
||||||
|
this.templateHtml = templateHtml;
|
||||||
|
}
|
||||||
|
|
||||||
|
processTemplate(template: Element, cmpMetadata: DirectiveMetadata) {
|
||||||
|
DOM.setInnerHTML(template, this.templateHtml);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -3,36 +3,16 @@ import {DirectiveMetadataReader} from 'angular2/src/core/compiler/directive_meta
|
||||||
import {Decorator, Component} from 'angular2/src/core/annotations/annotations';
|
import {Decorator, Component} from 'angular2/src/core/annotations/annotations';
|
||||||
import {TemplateConfig} from 'angular2/src/core/annotations/template_config';
|
import {TemplateConfig} from 'angular2/src/core/annotations/template_config';
|
||||||
import {DirectiveMetadata} from 'angular2/src/core/compiler/directive_metadata';
|
import {DirectiveMetadata} from 'angular2/src/core/compiler/directive_metadata';
|
||||||
import {ShadowDomStrategy, ShadowDomNative} from 'angular2/src/core/compiler/shadow_dom';
|
import {ShadowDomStrategy, NativeShadowDomStrategy} from 'angular2/src/core/compiler/shadow_dom_strategy';
|
||||||
import {CONST} from 'angular2/src/facade/lang';
|
import {CONST} from 'angular2/src/facade/lang';
|
||||||
|
|
||||||
|
|
||||||
class FakeShadowDomStrategy extends ShadowDomStrategy {
|
|
||||||
@CONST()
|
|
||||||
constructor() {}
|
|
||||||
|
|
||||||
polyfillDirectives() {
|
|
||||||
return [SomeDirective];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Decorator({
|
@Decorator({
|
||||||
selector: 'someSelector'
|
selector: 'someSelector'
|
||||||
})
|
})
|
||||||
class SomeDirective {
|
class SomeDirective {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'someSelector'
|
|
||||||
})
|
|
||||||
class ComponentWithoutExplicitShadowDomStrategy {}
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'someSelector',
|
|
||||||
shadowDom: new FakeShadowDomStrategy()
|
|
||||||
})
|
|
||||||
class ComponentWithExplicitShadowDomStrategy {}
|
|
||||||
|
|
||||||
class SomeDirectiveWithoutAnnotation {
|
class SomeDirectiveWithoutAnnotation {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,14 +35,14 @@ export function main() {
|
||||||
describe("DirectiveMetadataReader", () => {
|
describe("DirectiveMetadataReader", () => {
|
||||||
var reader;
|
var reader;
|
||||||
|
|
||||||
beforeEach( () => {
|
beforeEach(() => {
|
||||||
reader = new DirectiveMetadataReader();
|
reader = new DirectiveMetadataReader();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should read out the annotation', () => {
|
it('should read out the annotation', () => {
|
||||||
var directiveMetadata = reader.read(SomeDirective);
|
var directiveMetadata = reader.read(SomeDirective);
|
||||||
expect(directiveMetadata).toEqual(
|
expect(directiveMetadata).toEqual(
|
||||||
new DirectiveMetadata(SomeDirective, new Decorator({selector: 'someSelector'}), null, null));
|
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', () => {
|
||||||
|
@ -71,18 +51,6 @@ export function main() {
|
||||||
}).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).toBeAnInstanceOf(FakeShadowDomStrategy);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return Native otherwise', () => {
|
|
||||||
var directiveMetadata = reader.read(ComponentWithoutExplicitShadowDomStrategy);
|
|
||||||
expect(directiveMetadata.shadowDomStrategy).toEqual(ShadowDomNative);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("componentDirectives", () => {
|
describe("componentDirectives", () => {
|
||||||
it("should return an empty list when no directives specified", () => {
|
it("should return an empty list when no directives specified", () => {
|
||||||
var cmp = reader.read(ComponentWithoutDirectives);
|
var cmp = reader.read(ComponentWithoutDirectives);
|
||||||
|
@ -93,11 +61,6 @@ export function main() {
|
||||||
var cmp = reader.read(ComponentWithDirectives);
|
var cmp = reader.read(ComponentWithDirectives);
|
||||||
expect(cmp.componentDirectives).toEqual([ComponentWithoutDirectives]);
|
expect(cmp.componentDirectives).toEqual([ComponentWithoutDirectives]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should include directives required by the shadow DOM strategy", () => {
|
|
||||||
var cmp = reader.read(ComponentWithExplicitShadowDomStrategy);
|
|
||||||
expect(cmp.componentDirectives).toEqual([SomeDirective]);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
|
@ -7,7 +7,8 @@ import {Lexer, Parser, ChangeDetector, dynamicChangeDetection} from 'angular2/ch
|
||||||
|
|
||||||
import {Compiler, CompilerCache} from 'angular2/src/core/compiler/compiler';
|
import {Compiler, CompilerCache} from 'angular2/src/core/compiler/compiler';
|
||||||
import {DirectiveMetadataReader} from 'angular2/src/core/compiler/directive_metadata_reader';
|
import {DirectiveMetadataReader} from 'angular2/src/core/compiler/directive_metadata_reader';
|
||||||
import {ShadowDomEmulated} from 'angular2/src/core/compiler/shadow_dom';
|
import {NativeShadowDomStrategy} from 'angular2/src/core/compiler/shadow_dom_strategy';
|
||||||
|
import {TemplateLoader} from 'angular2/src/core/compiler/template_loader';
|
||||||
|
|
||||||
import {Decorator, Component, Template} from 'angular2/src/core/annotations/annotations';
|
import {Decorator, Component, Template} from 'angular2/src/core/annotations/annotations';
|
||||||
import {TemplateConfig} from 'angular2/src/core/annotations/template_config';
|
import {TemplateConfig} from 'angular2/src/core/annotations/template_config';
|
||||||
|
@ -15,13 +16,20 @@ import {TemplateConfig} from 'angular2/src/core/annotations/template_config';
|
||||||
import {ViewPort} from 'angular2/src/core/compiler/viewport';
|
import {ViewPort} from 'angular2/src/core/compiler/viewport';
|
||||||
import {MapWrapper} from 'angular2/src/facade/collection';
|
import {MapWrapper} from 'angular2/src/facade/collection';
|
||||||
|
|
||||||
|
import {XHRMock} from 'angular2/src/mock/xhr_mock';
|
||||||
|
|
||||||
export function main() {
|
export function main() {
|
||||||
describe('integration tests', function() {
|
describe('integration tests', function() {
|
||||||
var compiler;
|
var compiler;
|
||||||
|
|
||||||
beforeEach( () => {
|
beforeEach( () => {
|
||||||
compiler = new Compiler(dynamicChangeDetection, null, new DirectiveMetadataReader(),
|
compiler = new Compiler(dynamicChangeDetection,
|
||||||
new Parser(new Lexer()), new CompilerCache());
|
new TemplateLoader(new XHRMock()),
|
||||||
|
new DirectiveMetadataReader(),
|
||||||
|
new Parser(new Lexer()),
|
||||||
|
new CompilerCache(),
|
||||||
|
new NativeShadowDomStrategy()
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('react to record changes', function() {
|
describe('react to record changes', function() {
|
||||||
|
@ -69,22 +77,6 @@ export function main() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should consume element binding for class attribute', (done) => {
|
|
||||||
compiler.compile(MyComp, el('<div class="foo" [class.bar]="boolProp"></div>')).then((pv) => {
|
|
||||||
createView(pv);
|
|
||||||
|
|
||||||
ctx.boolProp = true;
|
|
||||||
cd.detectChanges();
|
|
||||||
expect(view.nodes[0].className).toEqual('foo ng-binding bar');
|
|
||||||
|
|
||||||
ctx.boolProp = false;
|
|
||||||
cd.detectChanges();
|
|
||||||
expect(view.nodes[0].className).toEqual('foo ng-binding');
|
|
||||||
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should support nested components.', (done) => {
|
it('should support nested components.', (done) => {
|
||||||
compiler.compile(MyComp, el('<child-cmp></child-cmp>')).then((pv) => {
|
compiler.compile(MyComp, el('<child-cmp></child-cmp>')).then((pv) => {
|
||||||
createView(pv);
|
createView(pv);
|
||||||
|
@ -163,7 +155,6 @@ class MyDir {
|
||||||
})
|
})
|
||||||
class MyComp {
|
class MyComp {
|
||||||
ctxProp:string;
|
ctxProp:string;
|
||||||
boolProp:boolean;
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.ctxProp = 'initial value';
|
this.ctxProp = 'initial value';
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import {CompileStep} from 'angular2/src/core/compiler/pipeline/compile_step';
|
||||||
import {CompileElement} from 'angular2/src/core/compiler/pipeline/compile_element';
|
import {CompileElement} from 'angular2/src/core/compiler/pipeline/compile_element';
|
||||||
import {CompileControl} from 'angular2/src/core/compiler/pipeline/compile_control';
|
import {CompileControl} from 'angular2/src/core/compiler/pipeline/compile_control';
|
||||||
import {DOM} from 'angular2/src/facade/dom';
|
import {DOM} from 'angular2/src/facade/dom';
|
||||||
|
import {NativeShadowDomStrategy, ShadowDomStrategy} from 'angular2/src/core/compiler/shadow_dom_strategy';
|
||||||
import {Component} from 'angular2/src/core/annotations/annotations';
|
import {Component} from 'angular2/src/core/annotations/annotations';
|
||||||
import {Decorator} from 'angular2/src/core/annotations/annotations';
|
import {Decorator} from 'angular2/src/core/annotations/annotations';
|
||||||
import {Template} from 'angular2/src/core/annotations/annotations';
|
import {Template} from 'angular2/src/core/annotations/annotations';
|
||||||
|
@ -182,7 +183,6 @@ export function main() {
|
||||||
}).toThrowError('Only template directives are allowed on <template> elements!');
|
}).toThrowError('Only template directives are allowed on <template> elements!');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ import {CompilePipeline} from 'angular2/src/core/compiler/pipeline/compile_pipel
|
||||||
import {CompileElement} from 'angular2/src/core/compiler/pipeline/compile_element';
|
import {CompileElement} from 'angular2/src/core/compiler/pipeline/compile_element';
|
||||||
import {CompileStep} from 'angular2/src/core/compiler/pipeline/compile_step'
|
import {CompileStep} from 'angular2/src/core/compiler/pipeline/compile_step'
|
||||||
import {CompileControl} from 'angular2/src/core/compiler/pipeline/compile_control';
|
import {CompileControl} from 'angular2/src/core/compiler/pipeline/compile_control';
|
||||||
|
import {NativeShadowDomStrategy} from 'angular2/src/core/compiler/shadow_dom_strategy';
|
||||||
|
|
||||||
import {Decorator} from 'angular2/src/core/annotations/annotations';
|
import {Decorator} from 'angular2/src/core/annotations/annotations';
|
||||||
import {Template} from 'angular2/src/core/annotations/annotations';
|
import {Template} from 'angular2/src/core/annotations/annotations';
|
||||||
|
@ -67,7 +68,8 @@ export function main() {
|
||||||
}
|
}
|
||||||
if (isPresent(current.element.getAttribute('viewroot'))) {
|
if (isPresent(current.element.getAttribute('viewroot'))) {
|
||||||
current.isViewRoot = true;
|
current.isViewRoot = true;
|
||||||
current.inheritedProtoView = new ProtoView(current.element, new DynamicProtoChangeDetector());
|
current.inheritedProtoView = new ProtoView(current.element,
|
||||||
|
new DynamicProtoChangeDetector(), new NativeShadowDomStrategy());
|
||||||
} else if (isPresent(parent)) {
|
} else if (isPresent(parent)) {
|
||||||
current.inheritedProtoView = parent.inheritedProtoView;
|
current.inheritedProtoView = parent.inheritedProtoView;
|
||||||
}
|
}
|
||||||
|
@ -176,27 +178,6 @@ export function main() {
|
||||||
expect(view.nodes[0].hidden).toEqual(false);
|
expect(view.nodes[0].hidden).toEqual(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should bind class with a dot', () => {
|
|
||||||
var propertyBindings = MapWrapper.createFromStringMap({
|
|
||||||
'class.bar': 'prop1',
|
|
||||||
});
|
|
||||||
var pipeline = createPipeline({propertyBindings: propertyBindings});
|
|
||||||
var results = pipeline.process(el('<input class="foo" viewroot prop-binding>'));
|
|
||||||
var pv = results[0].inheritedProtoView;
|
|
||||||
|
|
||||||
expect(pv.elementBinders[0].hasElementPropertyBindings).toBe(true);
|
|
||||||
|
|
||||||
instantiateView(pv);
|
|
||||||
|
|
||||||
evalContext.prop1 = true;
|
|
||||||
changeDetector.detectChanges();
|
|
||||||
expect(view.nodes[0].className).toEqual('foo ng-binding bar');
|
|
||||||
|
|
||||||
evalContext.prop1 = false;
|
|
||||||
changeDetector.detectChanges();
|
|
||||||
expect(view.nodes[0].className).toEqual('foo ng-binding');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should bind events', () => {
|
it('should bind events', () => {
|
||||||
var eventBindings = MapWrapper.createFromStringMap({
|
var eventBindings = MapWrapper.createFromStringMap({
|
||||||
'event1': '1+1'
|
'event1': '1+1'
|
||||||
|
@ -227,7 +208,7 @@ export function main() {
|
||||||
var results = pipeline.process(el('<div viewroot prop-binding directives></div>'));
|
var results = pipeline.process(el('<div viewroot prop-binding directives></div>'));
|
||||||
var pv = results[0].inheritedProtoView;
|
var pv = results[0].inheritedProtoView;
|
||||||
results[0].inheritedElementBinder.nestedProtoView = new ProtoView(
|
results[0].inheritedElementBinder.nestedProtoView = new ProtoView(
|
||||||
el('<div></div>'), new DynamicProtoChangeDetector());
|
el('<div></div>'), new DynamicProtoChangeDetector(), new NativeShadowDomStrategy());
|
||||||
|
|
||||||
instantiateView(pv);
|
instantiateView(pv);
|
||||||
evalContext.prop1 = 'a';
|
evalContext.prop1 = 'a';
|
||||||
|
|
|
@ -18,7 +18,7 @@ export function main() {
|
||||||
var protoElementInjectorBuilder, protoView;
|
var protoElementInjectorBuilder, protoView;
|
||||||
beforeEach( () => {
|
beforeEach( () => {
|
||||||
protoElementInjectorBuilder = new TestableProtoElementInjectorBuilder();
|
protoElementInjectorBuilder = new TestableProtoElementInjectorBuilder();
|
||||||
protoView = new ProtoView(null, null);
|
protoView = new ProtoView(null, null, null);
|
||||||
});
|
});
|
||||||
|
|
||||||
function createPipeline(directives = null) {
|
function createPipeline(directives = null) {
|
||||||
|
|
|
@ -7,12 +7,13 @@ import {CompilePipeline} from 'angular2/src/core/compiler/pipeline/compile_pipel
|
||||||
import {CompileElement} from 'angular2/src/core/compiler/pipeline/compile_element';
|
import {CompileElement} from 'angular2/src/core/compiler/pipeline/compile_element';
|
||||||
import {CompileStep} from 'angular2/src/core/compiler/pipeline/compile_step'
|
import {CompileStep} from 'angular2/src/core/compiler/pipeline/compile_step'
|
||||||
import {CompileControl} from 'angular2/src/core/compiler/pipeline/compile_control';
|
import {CompileControl} from 'angular2/src/core/compiler/pipeline/compile_control';
|
||||||
|
import {NativeShadowDomStrategy} from 'angular2/src/core/compiler/shadow_dom_strategy';
|
||||||
import {DOM} from 'angular2/src/facade/dom';
|
import {DOM} from 'angular2/src/facade/dom';
|
||||||
import {MapWrapper} from 'angular2/src/facade/collection';
|
import {MapWrapper} from 'angular2/src/facade/collection';
|
||||||
|
|
||||||
export function main() {
|
export function main() {
|
||||||
describe('ProtoViewBuilder', () => {
|
describe('ProtoViewBuilder', () => {
|
||||||
function createPipeline(variableBindings=null) {
|
function createPipeline(variableBindings = null) {
|
||||||
return new CompilePipeline([new MockStep((parent, current, control) => {
|
return new CompilePipeline([new MockStep((parent, current, control) => {
|
||||||
if (isPresent(current.element.getAttribute('viewroot'))) {
|
if (isPresent(current.element.getAttribute('viewroot'))) {
|
||||||
current.isViewRoot = true;
|
current.isViewRoot = true;
|
||||||
|
@ -21,7 +22,7 @@ export function main() {
|
||||||
current.variableBindings = MapWrapper.createFromStringMap(variableBindings);
|
current.variableBindings = MapWrapper.createFromStringMap(variableBindings);
|
||||||
}
|
}
|
||||||
current.inheritedElementBinder = new ElementBinder(null, null, null);
|
current.inheritedElementBinder = new ElementBinder(null, null, null);
|
||||||
}), new ProtoViewBuilder(dynamicChangeDetection)]);
|
}), new ProtoViewBuilder(dynamicChangeDetection, new NativeShadowDomStrategy())]);
|
||||||
}
|
}
|
||||||
|
|
||||||
it('should not create a ProtoView when the isViewRoot flag is not set', () => {
|
it('should not create a ProtoView when the isViewRoot flag is not set', () => {
|
||||||
|
|
|
@ -8,7 +8,10 @@ import {Lexer, Parser, ChangeDetector, dynamicChangeDetection} from 'angular2/ch
|
||||||
import {Compiler, CompilerCache} from 'angular2/src/core/compiler/compiler';
|
import {Compiler, CompilerCache} from 'angular2/src/core/compiler/compiler';
|
||||||
import {LifeCycle} from 'angular2/src/core/life_cycle/life_cycle';
|
import {LifeCycle} from 'angular2/src/core/life_cycle/life_cycle';
|
||||||
import {DirectiveMetadataReader} from 'angular2/src/core/compiler/directive_metadata_reader';
|
import {DirectiveMetadataReader} from 'angular2/src/core/compiler/directive_metadata_reader';
|
||||||
import {ShadowDomStrategy, ShadowDomNative, ShadowDomEmulated} from 'angular2/src/core/compiler/shadow_dom';
|
import {ShadowDomStrategy,
|
||||||
|
NativeShadowDomStrategy,
|
||||||
|
EmulatedShadowDomStrategy} from 'angular2/src/core/compiler/shadow_dom_strategy';
|
||||||
|
import {TemplateLoader} from 'angular2/src/core/compiler/template_loader';
|
||||||
|
|
||||||
import {Decorator, Component, Template} from 'angular2/src/core/annotations/annotations';
|
import {Decorator, Component, Template} from 'angular2/src/core/annotations/annotations';
|
||||||
import {TemplateConfig} from 'angular2/src/core/annotations/template_config';
|
import {TemplateConfig} from 'angular2/src/core/annotations/template_config';
|
||||||
|
@ -16,19 +19,28 @@ import {TemplateConfig} from 'angular2/src/core/annotations/template_config';
|
||||||
import {ViewPort} from 'angular2/src/core/compiler/viewport';
|
import {ViewPort} from 'angular2/src/core/compiler/viewport';
|
||||||
import {StringMapWrapper, MapWrapper} from 'angular2/src/facade/collection';
|
import {StringMapWrapper, MapWrapper} from 'angular2/src/facade/collection';
|
||||||
|
|
||||||
|
import {XHRMock} from 'angular2/src/mock/xhr_mock';
|
||||||
|
|
||||||
export function main() {
|
export function main() {
|
||||||
describe('integration tests', function() {
|
describe('integration tests', function() {
|
||||||
|
|
||||||
StringMapWrapper.forEach(
|
StringMapWrapper.forEach({
|
||||||
{"native" : ShadowDomNative, "emulated" : ShadowDomEmulated}, (strategy, name) => {
|
"native" : new NativeShadowDomStrategy(),
|
||||||
|
"emulated" : new EmulatedShadowDomStrategy()
|
||||||
|
},
|
||||||
|
(strategy, name) => {
|
||||||
|
|
||||||
describe(`${name} shadow dom strategy`, () => {
|
describe(`${name} shadow dom strategy`, () => {
|
||||||
var compiler;
|
var compiler;
|
||||||
|
|
||||||
beforeEach( () => {
|
beforeEach( () => {
|
||||||
compiler = new Compiler(dynamicChangeDetection, null,
|
compiler = new Compiler(dynamicChangeDetection,
|
||||||
new TestDirectiveMetadataReader(strategy),
|
new TemplateLoader(new XHRMock()),
|
||||||
new Parser(new Lexer()), new CompilerCache());
|
new DirectiveMetadataReader(),
|
||||||
|
new Parser(new Lexer()),
|
||||||
|
new CompilerCache(),
|
||||||
|
strategy
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
function compile(template, assertions) {
|
function compile(template, assertions) {
|
||||||
|
@ -297,6 +309,7 @@ class InnerInnerComponent {
|
||||||
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
selector: 'my-comp',
|
||||||
template: new TemplateConfig({
|
template: new TemplateConfig({
|
||||||
directives: [MultipleContentTagsComponent, ManualTemplateDirective,
|
directives: [MultipleContentTagsComponent, ManualTemplateDirective,
|
||||||
ConditionalContentComponent, OuterWithIndirectNestedComponent, OuterComponent]
|
ConditionalContentComponent, OuterWithIndirectNestedComponent, OuterComponent]
|
||||||
|
|
|
@ -0,0 +1,102 @@
|
||||||
|
import {describe, beforeEach, it, expect, ddescribe, iit, SpyObject, el} from 'angular2/test_lib';
|
||||||
|
import {shimCssText} from 'angular2/src/core/compiler/shadow_dom_emulation/shim_css';
|
||||||
|
|
||||||
|
import {RegExpWrapper, StringWrapper} from 'angular2/src/facade/lang';
|
||||||
|
|
||||||
|
export function main() {
|
||||||
|
describe('shim css', function() {
|
||||||
|
|
||||||
|
function s(css: string, tag:string) {
|
||||||
|
var shim = shimCssText(css, tag);
|
||||||
|
var nlRegexp = RegExpWrapper.create('\\n');
|
||||||
|
return StringWrapper.replaceAll(shim, nlRegexp, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
it('should handle empty string', () => {
|
||||||
|
expect(s('', 'a')).toEqual('');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should add an attribute to every rule', () => {
|
||||||
|
var css = 'one {color: red;}two {color: red;}';
|
||||||
|
var expected = 'one[a] {color: red;}two[a] {color: red;}';
|
||||||
|
expect(s(css, 'a')).toEqual(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should hanlde invalid css', () => {
|
||||||
|
var css = 'one {color: red;}garbage';
|
||||||
|
var expected = 'one[a] {color: red;}';
|
||||||
|
expect(s(css, 'a')).toEqual(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should add an attribute to every selector', () => {
|
||||||
|
var css = 'one, two {color: red;}';
|
||||||
|
var expected = 'one[a], two[a] {color: red;}';
|
||||||
|
expect(s(css, 'a')).toEqual(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle media rules', () => {
|
||||||
|
var css = '@media screen and (max-width: 800px) {div {font-size: 50px;}}';
|
||||||
|
var expected = '@media screen and (max-width: 800px) {div[a] {font-size: 50px;}}';
|
||||||
|
expect(s(css, 'a')).toEqual(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle media rules with simple rules', () => {
|
||||||
|
var css = '@media screen and (max-width: 800px) {div {font-size: 50px;}} div {}';
|
||||||
|
var expected = '@media screen and (max-width: 800px) {div[a] {font-size: 50px;}}div[a] {}';
|
||||||
|
expect(s(css, 'a')).toEqual(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle complicated selectors', () => {
|
||||||
|
expect(s('one::before {}', 'a')).toEqual('one[a]::before {}');
|
||||||
|
expect(s('one two {}', 'a')).toEqual('one[a] two[a] {}');
|
||||||
|
expect(s('one>two {}', 'a')).toEqual('one[a]>two[a] {}');
|
||||||
|
expect(s('one+two {}', 'a')).toEqual('one[a]+two[a] {}');
|
||||||
|
expect(s('one~two {}', 'a')).toEqual('one[a]~two[a] {}');
|
||||||
|
expect(s('.one.two > three {}', 'a')).toEqual('.one.two[a]>three[a] {}');
|
||||||
|
expect(s('one[attr="value"] {}', 'a')).toEqual('one[attr="value"][a] {}');
|
||||||
|
expect(s('one[attr=value] {}', 'a')).toEqual('one[attr=value][a] {}');
|
||||||
|
expect(s('one[attr^="value"] {}', 'a')).toEqual('one[attr^="value"][a] {}');
|
||||||
|
expect(s('one[attr\$="value"] {}', 'a')).toEqual('one[attr\$="value"][a] {}');
|
||||||
|
expect(s('one[attr*="value"] {}', 'a')).toEqual('one[attr*="value"][a] {}');
|
||||||
|
expect(s('one[attr|="value"] {}', 'a')).toEqual('one[attr|="value"][a] {}');
|
||||||
|
expect(s('one[attr] {}', 'a')).toEqual('one[attr][a] {}');
|
||||||
|
expect(s('[is="one"] {}', 'a')).toEqual('one[a] {}');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle :host', () => {
|
||||||
|
expect(s(':host {}', 'a')).toEqual('a {}');
|
||||||
|
expect(s(':host(.x,.y) {}', 'a')).toEqual('a.x, a.y {}');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should support polyfill-next-selector', () => {
|
||||||
|
var css = s("polyfill-next-selector {content: 'x > y'} z {}", 'a');
|
||||||
|
expect(css).toEqual('x[a]>y[a] {}');
|
||||||
|
|
||||||
|
css = s('polyfill-next-selector {content: "x > y"} z {}', 'a');
|
||||||
|
expect(css).toEqual('x[a]>y[a] {}');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should support polyfill-unscoped-next-selector', () => {
|
||||||
|
var css = s("polyfill-unscoped-next-selector {content: 'x > y'} z {}", 'a');
|
||||||
|
expect(css).toEqual('x > y {}');
|
||||||
|
|
||||||
|
css = s('polyfill-unscoped-next-selector {content: "x > y"} z {}', 'a');
|
||||||
|
expect(css).toEqual('x > y {}');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should support polyfill-non-strict-next-selector', () => {
|
||||||
|
var css = s('polyfill-non-strict {} one, two {}', 'a');
|
||||||
|
expect(css).toEqual('a one, a two {}');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle ::shadow', () => {
|
||||||
|
var css = s('polyfill-non-strict {} x::shadow > y {}', 'a');
|
||||||
|
expect(css).toEqual('a x > y {}');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle /deep/', () => {
|
||||||
|
var css = s('polyfill-non-strict {} x /deep/ y {}', 'a');
|
||||||
|
expect(css).toEqual('a x y {}');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
import {describe, xit, it, expect, beforeEach, ddescribe, iit, el} from 'angular2/test_lib';
|
||||||
|
import {NativeShadowDomStrategy, EmulatedShadowDomStrategy} from 'angular2/src/core/compiler/shadow_dom_strategy';
|
||||||
|
import {DOM} from 'angular2/src/facade/dom';
|
||||||
|
import {Component} from 'angular2/src/core/annotations/annotations';
|
||||||
|
import {DirectiveMetadata} from 'angular2/src/core/compiler/directive_metadata';
|
||||||
|
|
||||||
|
export function main() {
|
||||||
|
describe('Shadow DOM strategy', () => {
|
||||||
|
var strategy,
|
||||||
|
component = new Component({selector: 'mycmp'}),
|
||||||
|
metadata = new DirectiveMetadata(null, component, null);
|
||||||
|
|
||||||
|
describe('Native', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
strategy = new NativeShadowDomStrategy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should leave the styles in the template', () => {
|
||||||
|
var tpl = DOM.createTemplate('<style>.s1{}</style><div>content</div>');
|
||||||
|
strategy.processTemplate(tpl, metadata);
|
||||||
|
expect(tpl.content).toHaveText('.s1{}content');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not modify the content of the template', () => {
|
||||||
|
var html = '<p>content<span></span></p>';
|
||||||
|
var tpl = DOM.createTemplate(html);
|
||||||
|
strategy.processTemplate(tpl, metadata);
|
||||||
|
expect(DOM.getInnerHTML(tpl)).toEqual(html);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Emulated', () => {
|
||||||
|
var root;
|
||||||
|
beforeEach(() => {
|
||||||
|
root = el('<div>');
|
||||||
|
strategy = new EmulatedShadowDomStrategy(root);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should move the styles from the template to the root', () => {
|
||||||
|
var tpl = DOM.createTemplate('<style>.s1{}</style><div>content</div><style>.s2{}</style>');
|
||||||
|
strategy.processTemplate(tpl, metadata);
|
||||||
|
expect(root).toHaveText('.s1[mycmp] {}.s2[mycmp] {}');
|
||||||
|
expect(tpl.content).toHaveText('content');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should insert the styles as the first children of the host', () => {
|
||||||
|
DOM.setInnerHTML(root, '<p>root content</p>')
|
||||||
|
var tpl = DOM.createTemplate('<style>.s1{}</style><style>.s2{}</style>');
|
||||||
|
strategy.processTemplate(tpl, metadata);
|
||||||
|
expect(root).toHaveText('.s1[mycmp] {}.s2[mycmp] {}root content');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should add the component selector to all template children', () => {
|
||||||
|
var html = '<p>content<span></span></p>';
|
||||||
|
var processedHtml = '<p mycmp="">content<span mycmp=""></span></p>';
|
||||||
|
var tpl = DOM.createTemplate(html);
|
||||||
|
strategy.processTemplate(tpl, metadata);
|
||||||
|
expect(DOM.getInnerHTML(tpl)).toEqual(processedHtml);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
|
@ -0,0 +1,90 @@
|
||||||
|
import {describe, it, expect, beforeEach, ddescribe, iit, xit, el} from 'angular2/test_lib';
|
||||||
|
import {TemplateLoader} from 'angular2/src/core/compiler/template_loader';
|
||||||
|
import {Component} from 'angular2/src/core/annotations/annotations';
|
||||||
|
import {TemplateConfig} from 'angular2/src/core/annotations/template_config';
|
||||||
|
import {DirectiveMetadata} from 'angular2/src/core/compiler/directive_metadata';
|
||||||
|
|
||||||
|
import {PromiseWrapper} from 'angular2/src/facade/async';
|
||||||
|
|
||||||
|
import {XHRMock} from 'angular2/src/mock/xhr_mock';
|
||||||
|
|
||||||
|
export function main() {
|
||||||
|
describe('TemplateLoader', () => {
|
||||||
|
var loader, xhr;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
xhr = new XHRMock()
|
||||||
|
loader = new TemplateLoader(xhr);
|
||||||
|
});
|
||||||
|
|
||||||
|
function createMetadata({inline = null, url = null}={}) {
|
||||||
|
var config = new TemplateConfig({url: url, inline: inline});
|
||||||
|
var component = new Component({template: config});
|
||||||
|
return new DirectiveMetadata(FakeComponent, component, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
it('should load inline templates', (done) => {
|
||||||
|
var template = 'inline template';
|
||||||
|
var md = createMetadata({inline: template});
|
||||||
|
loader.load(md).then((el) => {
|
||||||
|
expect(el.content).toHaveText(template);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should load templates through XHR', (done) => {
|
||||||
|
var url = '/foo';
|
||||||
|
var template = 'xhr template';
|
||||||
|
xhr.expect(url, template);
|
||||||
|
var md = createMetadata({url: '/foo'});
|
||||||
|
loader.load(md).then((el) => {
|
||||||
|
expect(el.content).toHaveText(template);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
xhr.flush();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should cache template loaded through XHR', (done) => {
|
||||||
|
var firstEl;
|
||||||
|
var url = '/foo';
|
||||||
|
var template = 'xhr template';
|
||||||
|
xhr.expect(url, template);
|
||||||
|
var md = createMetadata({url: '/foo'});
|
||||||
|
loader.load(md)
|
||||||
|
.then((el) => {
|
||||||
|
firstEl = el;
|
||||||
|
return loader.load(md);
|
||||||
|
})
|
||||||
|
.then((el) =>{
|
||||||
|
expect(el).toBe(firstEl);
|
||||||
|
expect(el.content).toHaveText(template);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
xhr.flush();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw when no template is defined', () => {
|
||||||
|
var md = createMetadata();
|
||||||
|
expect(() => loader.load(md))
|
||||||
|
.toThrowError('No template configured for component FakeComponent');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return a rejected Promise when xhr loading fails', (done) => {
|
||||||
|
var url = '/foo';
|
||||||
|
xhr.expect(url, null);
|
||||||
|
var md = createMetadata({url: '/foo'});
|
||||||
|
PromiseWrapper.then(loader.load(md),
|
||||||
|
function(_) { throw 'Unexpected response'; },
|
||||||
|
function(error) {
|
||||||
|
expect(error).toEqual('Failed to load /foo');
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
)
|
||||||
|
xhr.flush();
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
class FakeComponent {
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
import {describe, xit, it, expect, beforeEach, ddescribe, iit, el} from 'angular2/test_lib';
|
import {describe, xit, it, expect, beforeEach, ddescribe, iit, el} from 'angular2/test_lib';
|
||||||
import {ProtoView, ElementPropertyMemento, DirectivePropertyMemento} from 'angular2/src/core/compiler/view';
|
import {ProtoView, ElementPropertyMemento, DirectivePropertyMemento} from 'angular2/src/core/compiler/view';
|
||||||
import {ProtoElementInjector, ElementInjector} from 'angular2/src/core/compiler/element_injector';
|
import {ProtoElementInjector, ElementInjector} from 'angular2/src/core/compiler/element_injector';
|
||||||
import {ShadowDomEmulated} from 'angular2/src/core/compiler/shadow_dom';
|
import {EmulatedShadowDomStrategy, NativeShadowDomStrategy} from 'angular2/src/core/compiler/shadow_dom_strategy';
|
||||||
import {DirectiveMetadataReader} from 'angular2/src/core/compiler/directive_metadata_reader';
|
import {DirectiveMetadataReader} from 'angular2/src/core/compiler/directive_metadata_reader';
|
||||||
import {Component, Decorator, Template} from 'angular2/src/core/annotations/annotations';
|
import {Component, Decorator, Template} from 'angular2/src/core/annotations/annotations';
|
||||||
import {OnChange} from 'angular2/core';
|
import {OnChange} from 'angular2/core';
|
||||||
|
@ -53,7 +53,7 @@ export function main() {
|
||||||
describe('instantiated from protoView', () => {
|
describe('instantiated from protoView', () => {
|
||||||
var view;
|
var view;
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
var pv = new ProtoView(el('<div id="1"></div>'), new DynamicProtoChangeDetector());
|
var pv = new ProtoView(el('<div id="1"></div>'), new DynamicProtoChangeDetector(), null);
|
||||||
view = pv.instantiate(null);
|
view = pv.instantiate(null);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@ export function main() {
|
||||||
describe('with locals', function() {
|
describe('with locals', function() {
|
||||||
var view;
|
var view;
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
var pv = new ProtoView(el('<div id="1"></div>'), new DynamicProtoChangeDetector());
|
var pv = new ProtoView(el('<div id="1"></div>'), new DynamicProtoChangeDetector(), null);
|
||||||
pv.bindVariable('context-foo', 'template-foo');
|
pv.bindVariable('context-foo', 'template-foo');
|
||||||
view = createView(pv);
|
view = createView(pv);
|
||||||
});
|
});
|
||||||
|
@ -110,7 +110,8 @@ export function main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
it('should collect the root node in the ProtoView element', () => {
|
it('should collect the root node in the ProtoView element', () => {
|
||||||
var pv = new ProtoView(templateAwareCreateElement('<div id="1"></div>'), new DynamicProtoChangeDetector());
|
var pv = new ProtoView(templateAwareCreateElement('<div id="1"></div>'),
|
||||||
|
new DynamicProtoChangeDetector(), null);
|
||||||
var view = pv.instantiate(null);
|
var view = pv.instantiate(null);
|
||||||
view.hydrate(null, null, null);
|
view.hydrate(null, null, null);
|
||||||
expect(view.nodes.length).toBe(1);
|
expect(view.nodes.length).toBe(1);
|
||||||
|
@ -120,7 +121,8 @@ export function main() {
|
||||||
describe('collect elements with property bindings', () => {
|
describe('collect elements with property bindings', () => {
|
||||||
|
|
||||||
it('should collect property bindings on the root element if it has the ng-binding class', () => {
|
it('should collect property bindings on the root element if it has the ng-binding class', () => {
|
||||||
var pv = new ProtoView(templateAwareCreateElement('<div [prop]="a" class="ng-binding"></div>'), new DynamicProtoChangeDetector());
|
var pv = new ProtoView(templateAwareCreateElement('<div [prop]="a" class="ng-binding"></div>'),
|
||||||
|
new DynamicProtoChangeDetector(), null);
|
||||||
pv.bindElement(null);
|
pv.bindElement(null);
|
||||||
pv.bindElementProperty(parser.parseBinding('a', null), 'prop', reflector.setter('prop'));
|
pv.bindElementProperty(parser.parseBinding('a', null), 'prop', reflector.setter('prop'));
|
||||||
|
|
||||||
|
@ -132,7 +134,7 @@ export function main() {
|
||||||
|
|
||||||
it('should collect property bindings on child elements with ng-binding class', () => {
|
it('should collect property bindings on child elements with ng-binding class', () => {
|
||||||
var pv = new ProtoView(templateAwareCreateElement('<div><span></span><span class="ng-binding"></span></div>'),
|
var pv = new ProtoView(templateAwareCreateElement('<div><span></span><span class="ng-binding"></span></div>'),
|
||||||
new DynamicProtoChangeDetector());
|
new DynamicProtoChangeDetector(), null);
|
||||||
pv.bindElement(null);
|
pv.bindElement(null);
|
||||||
pv.bindElementProperty(parser.parseBinding('b', null), 'a', reflector.setter('a'));
|
pv.bindElementProperty(parser.parseBinding('b', null), 'a', reflector.setter('a'));
|
||||||
|
|
||||||
|
@ -147,7 +149,8 @@ export function main() {
|
||||||
describe('collect text nodes with bindings', () => {
|
describe('collect text nodes with bindings', () => {
|
||||||
|
|
||||||
it('should collect text nodes under the root element', () => {
|
it('should collect text nodes under the root element', () => {
|
||||||
var pv = new ProtoView(templateAwareCreateElement('<div class="ng-binding">{{}}<span></span>{{}}</div>'), new DynamicProtoChangeDetector());
|
var pv = new ProtoView(templateAwareCreateElement('<div class="ng-binding">{{}}<span></span>{{}}</div>'),
|
||||||
|
new DynamicProtoChangeDetector(), null);
|
||||||
pv.bindElement(null);
|
pv.bindElement(null);
|
||||||
pv.bindTextNode(0, parser.parseBinding('a', null));
|
pv.bindTextNode(0, parser.parseBinding('a', null));
|
||||||
pv.bindTextNode(2, parser.parseBinding('b', null));
|
pv.bindTextNode(2, parser.parseBinding('b', null));
|
||||||
|
@ -161,7 +164,7 @@ export function main() {
|
||||||
|
|
||||||
it('should collect text nodes with bindings on child elements with ng-binding class', () => {
|
it('should collect text nodes with bindings on child elements with ng-binding class', () => {
|
||||||
var pv = new ProtoView(templateAwareCreateElement('<div><span> </span><span class="ng-binding">{{}}</span></div>'),
|
var pv = new ProtoView(templateAwareCreateElement('<div><span> </span><span class="ng-binding">{{}}</span></div>'),
|
||||||
new DynamicProtoChangeDetector());
|
new DynamicProtoChangeDetector(), null);
|
||||||
pv.bindElement(null);
|
pv.bindElement(null);
|
||||||
pv.bindTextNode(0, parser.parseBinding('b', null));
|
pv.bindTextNode(0, parser.parseBinding('b', null));
|
||||||
|
|
||||||
|
@ -177,7 +180,8 @@ export function main() {
|
||||||
describe('inplace instantiation', () => {
|
describe('inplace instantiation', () => {
|
||||||
it('should be supported.', () => {
|
it('should be supported.', () => {
|
||||||
var template = el('<div></div>');
|
var template = el('<div></div>');
|
||||||
var pv = new ProtoView(template, new DynamicProtoChangeDetector());
|
var pv = new ProtoView(template, new DynamicProtoChangeDetector(),
|
||||||
|
new NativeShadowDomStrategy());
|
||||||
pv.instantiateInPlace = true;
|
pv.instantiateInPlace = true;
|
||||||
var view = pv.instantiate(null);
|
var view = pv.instantiate(null);
|
||||||
view.hydrate(null, null, null);
|
view.hydrate(null, null, null);
|
||||||
|
@ -186,7 +190,8 @@ export function main() {
|
||||||
|
|
||||||
it('should be off by default.', () => {
|
it('should be off by default.', () => {
|
||||||
var template = el('<div></div>')
|
var template = el('<div></div>')
|
||||||
var view = new ProtoView(template, new DynamicProtoChangeDetector())
|
var view = new ProtoView(template, new DynamicProtoChangeDetector(),
|
||||||
|
new NativeShadowDomStrategy())
|
||||||
.instantiate(null);
|
.instantiate(null);
|
||||||
view.hydrate(null, null, null);
|
view.hydrate(null, null, null);
|
||||||
expect(view.nodes[0]).not.toBe(template);
|
expect(view.nodes[0]).not.toBe(template);
|
||||||
|
@ -203,7 +208,8 @@ export function main() {
|
||||||
|
|
||||||
describe('create ElementInjectors', () => {
|
describe('create ElementInjectors', () => {
|
||||||
it('should use the directives of the ProtoElementInjector', () => {
|
it('should use the directives of the ProtoElementInjector', () => {
|
||||||
var pv = new ProtoView(el('<div class="ng-binding"></div>'), new DynamicProtoChangeDetector());
|
var pv = new ProtoView(el('<div class="ng-binding"></div>'),
|
||||||
|
new DynamicProtoChangeDetector(), null);
|
||||||
pv.bindElement(new ProtoElementInjector(null, 1, [SomeDirective]));
|
pv.bindElement(new ProtoElementInjector(null, 1, [SomeDirective]));
|
||||||
|
|
||||||
var view = pv.instantiate(null);
|
var view = pv.instantiate(null);
|
||||||
|
@ -214,7 +220,7 @@ export function main() {
|
||||||
|
|
||||||
it('should use the correct parent', () => {
|
it('should use the correct parent', () => {
|
||||||
var pv = new ProtoView(el('<div class="ng-binding"><span class="ng-binding"></span></div>'),
|
var pv = new ProtoView(el('<div class="ng-binding"><span class="ng-binding"></span></div>'),
|
||||||
new DynamicProtoChangeDetector());
|
new DynamicProtoChangeDetector(), null);
|
||||||
var protoParent = new ProtoElementInjector(null, 0, [SomeDirective]);
|
var protoParent = new ProtoElementInjector(null, 0, [SomeDirective]);
|
||||||
pv.bindElement(protoParent);
|
pv.bindElement(protoParent);
|
||||||
pv.bindElement(new ProtoElementInjector(protoParent, 1, [AnotherDirective]));
|
pv.bindElement(new ProtoElementInjector(protoParent, 1, [AnotherDirective]));
|
||||||
|
@ -228,7 +234,7 @@ export function main() {
|
||||||
|
|
||||||
it('should not pass the host injector when a parent injector exists', () => {
|
it('should not pass the host injector when a parent injector exists', () => {
|
||||||
var pv = new ProtoView(el('<div class="ng-binding"><span class="ng-binding"></span></div>'),
|
var pv = new ProtoView(el('<div class="ng-binding"><span class="ng-binding"></span></div>'),
|
||||||
new DynamicProtoChangeDetector());
|
new DynamicProtoChangeDetector(), null);
|
||||||
var protoParent = new ProtoElementInjector(null, 0, [SomeDirective]);
|
var protoParent = new ProtoElementInjector(null, 0, [SomeDirective]);
|
||||||
pv.bindElement(protoParent);
|
pv.bindElement(protoParent);
|
||||||
var testProtoElementInjector = new TestProtoElementInjector(protoParent, 1, [AnotherDirective]);
|
var testProtoElementInjector = new TestProtoElementInjector(protoParent, 1, [AnotherDirective]);
|
||||||
|
@ -244,7 +250,7 @@ export function main() {
|
||||||
|
|
||||||
it('should pass the host injector when there is no parent injector', () => {
|
it('should pass the host injector when there is no parent injector', () => {
|
||||||
var pv = new ProtoView(el('<div class="ng-binding"><span class="ng-binding"></span></div>'),
|
var pv = new ProtoView(el('<div class="ng-binding"><span class="ng-binding"></span></div>'),
|
||||||
new DynamicProtoChangeDetector());
|
new DynamicProtoChangeDetector(), null);
|
||||||
pv.bindElement(new ProtoElementInjector(null, 0, [SomeDirective]));
|
pv.bindElement(new ProtoElementInjector(null, 0, [SomeDirective]));
|
||||||
var testProtoElementInjector = new TestProtoElementInjector(null, 1, [AnotherDirective]);
|
var testProtoElementInjector = new TestProtoElementInjector(null, 1, [AnotherDirective]);
|
||||||
pv.bindElement(testProtoElementInjector);
|
pv.bindElement(testProtoElementInjector);
|
||||||
|
@ -261,7 +267,7 @@ export function main() {
|
||||||
|
|
||||||
it('should collect a single root element injector', () => {
|
it('should collect a single root element injector', () => {
|
||||||
var pv = new ProtoView(el('<div class="ng-binding"><span class="ng-binding"></span></div>'),
|
var pv = new ProtoView(el('<div class="ng-binding"><span class="ng-binding"></span></div>'),
|
||||||
new DynamicProtoChangeDetector());
|
new DynamicProtoChangeDetector(), null);
|
||||||
var protoParent = new ProtoElementInjector(null, 0, [SomeDirective]);
|
var protoParent = new ProtoElementInjector(null, 0, [SomeDirective]);
|
||||||
pv.bindElement(protoParent);
|
pv.bindElement(protoParent);
|
||||||
pv.bindElement(new ProtoElementInjector(protoParent, 1, [AnotherDirective]));
|
pv.bindElement(new ProtoElementInjector(protoParent, 1, [AnotherDirective]));
|
||||||
|
@ -274,7 +280,7 @@ export function main() {
|
||||||
|
|
||||||
it('should collect multiple root element injectors', () => {
|
it('should collect multiple root element injectors', () => {
|
||||||
var pv = new ProtoView(el('<div><span class="ng-binding"></span><span class="ng-binding"></span></div>'),
|
var pv = new ProtoView(el('<div><span class="ng-binding"></span><span class="ng-binding"></span></div>'),
|
||||||
new DynamicProtoChangeDetector());
|
new DynamicProtoChangeDetector(), null);
|
||||||
pv.bindElement(new ProtoElementInjector(null, 1, [SomeDirective]));
|
pv.bindElement(new ProtoElementInjector(null, 1, [SomeDirective]));
|
||||||
pv.bindElement(new ProtoElementInjector(null, 2, [AnotherDirective]));
|
pv.bindElement(new ProtoElementInjector(null, 2, [AnotherDirective]));
|
||||||
|
|
||||||
|
@ -291,7 +297,8 @@ export function main() {
|
||||||
var ctx;
|
var ctx;
|
||||||
|
|
||||||
function createComponentWithSubPV(subProtoView) {
|
function createComponentWithSubPV(subProtoView) {
|
||||||
var pv = new ProtoView(el('<cmp class="ng-binding"></cmp>'), new DynamicProtoChangeDetector());
|
var pv = new ProtoView(el('<cmp class="ng-binding"></cmp>'),
|
||||||
|
new DynamicProtoChangeDetector(), new NativeShadowDomStrategy());
|
||||||
var binder = pv.bindElement(new ProtoElementInjector(null, 0, [SomeComponent], true));
|
var binder = pv.bindElement(new ProtoElementInjector(null, 0, [SomeComponent], true));
|
||||||
binder.componentDirective = someComponentDirective;
|
binder.componentDirective = someComponentDirective;
|
||||||
binder.nestedProtoView = subProtoView;
|
binder.nestedProtoView = subProtoView;
|
||||||
|
@ -306,7 +313,7 @@ export function main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
it('should expose component services to the component', () => {
|
it('should expose component services to the component', () => {
|
||||||
var subpv = new ProtoView(el('<span></span>'), new DynamicProtoChangeDetector());
|
var subpv = new ProtoView(el('<span></span>'), new DynamicProtoChangeDetector(), null);
|
||||||
var pv = createComponentWithSubPV(subpv);
|
var pv = createComponentWithSubPV(subpv);
|
||||||
|
|
||||||
var view = createNestedView(pv);
|
var view = createNestedView(pv);
|
||||||
|
@ -318,7 +325,9 @@ export function main() {
|
||||||
it('should expose component services and component instance to directives in the shadow Dom',
|
it('should expose component services and component instance to directives in the shadow Dom',
|
||||||
() => {
|
() => {
|
||||||
var subpv = new ProtoView(
|
var subpv = new ProtoView(
|
||||||
el('<div dec class="ng-binding">hello shadow dom</div>'), new DynamicProtoChangeDetector());
|
el('<div dec class="ng-binding">hello shadow dom</div>'),
|
||||||
|
new DynamicProtoChangeDetector(),
|
||||||
|
null);
|
||||||
subpv.bindElement(
|
subpv.bindElement(
|
||||||
new ProtoElementInjector(null, 0, [ServiceDependentDecorator]));
|
new ProtoElementInjector(null, 0, [ServiceDependentDecorator]));
|
||||||
var pv = createComponentWithSubPV(subpv);
|
var pv = createComponentWithSubPV(subpv);
|
||||||
|
@ -341,7 +350,9 @@ export function main() {
|
||||||
|
|
||||||
it('dehydration should dehydrate child component views too', () => {
|
it('dehydration should dehydrate child component views too', () => {
|
||||||
var subpv = new ProtoView(
|
var subpv = new ProtoView(
|
||||||
el('<div dec class="ng-binding">hello shadow dom</div>'), new DynamicProtoChangeDetector());
|
el('<div dec class="ng-binding">hello shadow dom</div>'),
|
||||||
|
new DynamicProtoChangeDetector(),
|
||||||
|
null);
|
||||||
subpv.bindElement(
|
subpv.bindElement(
|
||||||
new ProtoElementInjector(null, 0, [ServiceDependentDecorator]));
|
new ProtoElementInjector(null, 0, [ServiceDependentDecorator]));
|
||||||
var pv = createComponentWithSubPV(subpv);
|
var pv = createComponentWithSubPV(subpv);
|
||||||
|
@ -356,7 +367,9 @@ export function main() {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should create shadow dom', () => {
|
it('should create shadow dom', () => {
|
||||||
var subpv = new ProtoView(el('<span>hello shadow dom</span>'), new DynamicProtoChangeDetector());
|
var subpv = new ProtoView(el('<span>hello shadow dom</span>'),
|
||||||
|
new DynamicProtoChangeDetector(),
|
||||||
|
null);
|
||||||
var pv = createComponentWithSubPV(subpv);
|
var pv = createComponentWithSubPV(subpv);
|
||||||
|
|
||||||
var view = createNestedView(pv);
|
var view = createNestedView(pv);
|
||||||
|
@ -365,9 +378,11 @@ export function main() {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should use the provided shadow DOM strategy', () => {
|
it('should use the provided shadow DOM strategy', () => {
|
||||||
var subpv = new ProtoView(el('<span>hello shadow dom</span>'), new DynamicProtoChangeDetector());
|
var subpv = new ProtoView(el('<span>hello shadow dom</span>'),
|
||||||
|
new DynamicProtoChangeDetector(), null);
|
||||||
|
|
||||||
var pv = new ProtoView(el('<cmp class="ng-binding"></cmp>'), new DynamicProtoChangeDetector());
|
var pv = new ProtoView(el('<cmp class="ng-binding"></cmp>'),
|
||||||
|
new DynamicProtoChangeDetector(), new EmulatedShadowDomStrategy());
|
||||||
var binder = pv.bindElement(new ProtoElementInjector(null, 0, [SomeComponentWithEmulatedShadowDom], true));
|
var binder = pv.bindElement(new ProtoElementInjector(null, 0, [SomeComponentWithEmulatedShadowDom], true));
|
||||||
binder.componentDirective = new DirectiveMetadataReader().read(SomeComponentWithEmulatedShadowDom);
|
binder.componentDirective = new DirectiveMetadataReader().read(SomeComponentWithEmulatedShadowDom);
|
||||||
binder.nestedProtoView = subpv;
|
binder.nestedProtoView = subpv;
|
||||||
|
@ -381,8 +396,9 @@ export function main() {
|
||||||
describe('with template views', () => {
|
describe('with template views', () => {
|
||||||
function createViewWithTemplate() {
|
function createViewWithTemplate() {
|
||||||
var templateProtoView = new ProtoView(
|
var templateProtoView = new ProtoView(
|
||||||
el('<div id="1"></div>'), new DynamicProtoChangeDetector());
|
el('<div id="1"></div>'), new DynamicProtoChangeDetector(), null);
|
||||||
var pv = new ProtoView(el('<someTmpl class="ng-binding"></someTmpl>'), new DynamicProtoChangeDetector());
|
var pv = new ProtoView(el('<someTmpl class="ng-binding"></someTmpl>'),
|
||||||
|
new DynamicProtoChangeDetector(), new NativeShadowDomStrategy());
|
||||||
var binder = pv.bindElement(new ProtoElementInjector(null, 0, [SomeTemplate]));
|
var binder = pv.bindElement(new ProtoElementInjector(null, 0, [SomeTemplate]));
|
||||||
binder.templateDirective = someTemplateDirective;
|
binder.templateDirective = someTemplateDirective;
|
||||||
binder.nestedProtoView = templateProtoView;
|
binder.nestedProtoView = templateProtoView;
|
||||||
|
@ -426,7 +442,7 @@ export function main() {
|
||||||
|
|
||||||
function createProtoView() {
|
function createProtoView() {
|
||||||
var pv = new ProtoView(el('<div class="ng-binding"><div></div></div>'),
|
var pv = new ProtoView(el('<div class="ng-binding"><div></div></div>'),
|
||||||
new DynamicProtoChangeDetector());
|
new DynamicProtoChangeDetector(), null);
|
||||||
pv.bindElement(new TestProtoElementInjector(null, 0, []));
|
pv.bindElement(new TestProtoElementInjector(null, 0, []));
|
||||||
pv.bindEvent('click', parser.parseBinding('callMe(\$event)', null));
|
pv.bindEvent('click', parser.parseBinding('callMe(\$event)', null));
|
||||||
return pv;
|
return pv;
|
||||||
|
@ -461,7 +477,7 @@ export function main() {
|
||||||
|
|
||||||
it('should support custom event emitters', () => {
|
it('should support custom event emitters', () => {
|
||||||
var pv = new ProtoView(el('<div class="ng-binding"><div></div></div>'),
|
var pv = new ProtoView(el('<div class="ng-binding"><div></div></div>'),
|
||||||
new DynamicProtoChangeDetector());
|
new DynamicProtoChangeDetector(), null);
|
||||||
pv.bindElement(new TestProtoElementInjector(null, 0, [EventEmitterDirective]));
|
pv.bindElement(new TestProtoElementInjector(null, 0, [EventEmitterDirective]));
|
||||||
pv.bindEvent('click', parser.parseBinding('callMe(\$event)', null));
|
pv.bindEvent('click', parser.parseBinding('callMe(\$event)', null));
|
||||||
|
|
||||||
|
@ -492,7 +508,7 @@ export function main() {
|
||||||
|
|
||||||
it('should consume text node changes', () => {
|
it('should consume text node changes', () => {
|
||||||
var pv = new ProtoView(el('<div class="ng-binding">{{}}</div>'),
|
var pv = new ProtoView(el('<div class="ng-binding">{{}}</div>'),
|
||||||
new DynamicProtoChangeDetector());
|
new DynamicProtoChangeDetector(), null);
|
||||||
pv.bindElement(null);
|
pv.bindElement(null);
|
||||||
pv.bindTextNode(0, parser.parseBinding('foo', null));
|
pv.bindTextNode(0, parser.parseBinding('foo', null));
|
||||||
createViewAndChangeDetector(pv);
|
createViewAndChangeDetector(pv);
|
||||||
|
@ -504,7 +520,7 @@ export function main() {
|
||||||
|
|
||||||
it('should consume element binding changes', () => {
|
it('should consume element binding changes', () => {
|
||||||
var pv = new ProtoView(el('<div class="ng-binding"></div>'),
|
var pv = new ProtoView(el('<div class="ng-binding"></div>'),
|
||||||
new DynamicProtoChangeDetector());
|
new DynamicProtoChangeDetector(), null);
|
||||||
pv.bindElement(null);
|
pv.bindElement(null);
|
||||||
pv.bindElementProperty(parser.parseBinding('foo', null), 'id', reflector.setter('id'));
|
pv.bindElementProperty(parser.parseBinding('foo', null), 'id', reflector.setter('id'));
|
||||||
createViewAndChangeDetector(pv);
|
createViewAndChangeDetector(pv);
|
||||||
|
@ -516,7 +532,7 @@ export function main() {
|
||||||
|
|
||||||
it('should consume directive watch expression change', () => {
|
it('should consume directive watch expression change', () => {
|
||||||
var pv = new ProtoView(el('<div class="ng-binding"></div>'),
|
var pv = new ProtoView(el('<div class="ng-binding"></div>'),
|
||||||
new DynamicProtoChangeDetector());
|
new DynamicProtoChangeDetector(), null);
|
||||||
pv.bindElement(new ProtoElementInjector(null, 0, [SomeDirective]));
|
pv.bindElement(new ProtoElementInjector(null, 0, [SomeDirective]));
|
||||||
pv.bindDirectiveProperty(0, parser.parseBinding('foo', null), 'prop', reflector.setter('prop'), false);
|
pv.bindDirectiveProperty(0, parser.parseBinding('foo', null), 'prop', reflector.setter('prop'), false);
|
||||||
createViewAndChangeDetector(pv);
|
createViewAndChangeDetector(pv);
|
||||||
|
@ -528,7 +544,7 @@ export function main() {
|
||||||
|
|
||||||
it('should notify a directive about changes after all its properties have been set', () => {
|
it('should notify a directive about changes after all its properties have been set', () => {
|
||||||
var pv = new ProtoView(el('<div class="ng-binding"></div>'),
|
var pv = new ProtoView(el('<div class="ng-binding"></div>'),
|
||||||
new DynamicProtoChangeDetector());
|
new DynamicProtoChangeDetector(), null);
|
||||||
|
|
||||||
pv.bindElement(new ProtoElementInjector(null, 0, [DirectiveImplementingOnChange]));
|
pv.bindElement(new ProtoElementInjector(null, 0, [DirectiveImplementingOnChange]));
|
||||||
pv.bindDirectiveProperty( 0, parser.parseBinding('a', null), 'a', reflector.setter('a'), false);
|
pv.bindDirectiveProperty( 0, parser.parseBinding('a', null), 'a', reflector.setter('a'), false);
|
||||||
|
@ -545,7 +561,7 @@ export function main() {
|
||||||
|
|
||||||
it('should provide a map of updated properties', () => {
|
it('should provide a map of updated properties', () => {
|
||||||
var pv = new ProtoView(el('<div class="ng-binding"></div>'),
|
var pv = new ProtoView(el('<div class="ng-binding"></div>'),
|
||||||
new DynamicProtoChangeDetector());
|
new DynamicProtoChangeDetector(), null);
|
||||||
|
|
||||||
pv.bindElement(new ProtoElementInjector(null, 0, [DirectiveImplementingOnChange]));
|
pv.bindElement(new ProtoElementInjector(null, 0, [DirectiveImplementingOnChange]));
|
||||||
pv.bindDirectiveProperty( 0, parser.parseBinding('a', null), 'a', reflector.setter('a'), false);
|
pv.bindDirectiveProperty( 0, parser.parseBinding('a', null), 'a', reflector.setter('a'), false);
|
||||||
|
@ -570,12 +586,13 @@ export function main() {
|
||||||
var element, pv;
|
var element, pv;
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
element = DOM.createElement('div');
|
element = DOM.createElement('div');
|
||||||
pv = new ProtoView(el('<div>hi</div>'), new DynamicProtoChangeDetector());
|
pv = new ProtoView(el('<div>hi</div>'), new DynamicProtoChangeDetector(),
|
||||||
|
new NativeShadowDomStrategy());
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should create the root component when instantiated', () => {
|
it('should create the root component when instantiated', () => {
|
||||||
var rootProtoView = ProtoView.createRootProtoView(pv, element,
|
var rootProtoView = ProtoView.createRootProtoView(pv, element,
|
||||||
someComponentDirective, new DynamicProtoChangeDetector());
|
someComponentDirective, new DynamicProtoChangeDetector(), new NativeShadowDomStrategy());
|
||||||
var view = rootProtoView.instantiate(null);
|
var view = rootProtoView.instantiate(null);
|
||||||
view.hydrate(new Injector([]), null, null);
|
view.hydrate(new Injector([]), null, null);
|
||||||
expect(view.rootElementInjectors[0].get(SomeComponent)).not.toBe(null);
|
expect(view.rootElementInjectors[0].get(SomeComponent)).not.toBe(null);
|
||||||
|
@ -583,7 +600,7 @@ export function main() {
|
||||||
|
|
||||||
it('should inject the protoView into the shadowDom', () => {
|
it('should inject the protoView into the shadowDom', () => {
|
||||||
var rootProtoView = ProtoView.createRootProtoView(pv, element,
|
var rootProtoView = ProtoView.createRootProtoView(pv, element,
|
||||||
someComponentDirective, new DynamicProtoChangeDetector());
|
someComponentDirective, new DynamicProtoChangeDetector(), new NativeShadowDomStrategy());
|
||||||
var view = rootProtoView.instantiate(null);
|
var view = rootProtoView.instantiate(null);
|
||||||
view.hydrate(new Injector([]), null, null);
|
view.hydrate(new Injector([]), null, null);
|
||||||
expect(element.shadowRoot.childNodes[0].childNodes[0].nodeValue).toEqual('hi');
|
expect(element.shadowRoot.childNodes[0].childNodes[0].nodeValue).toEqual('hi');
|
||||||
|
@ -624,7 +641,7 @@ class SomeComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
shadowDom: ShadowDomEmulated
|
componentServices: []
|
||||||
})
|
})
|
||||||
class SomeComponentWithEmulatedShadowDom {
|
class SomeComponentWithEmulatedShadowDom {
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import {DOM} from 'angular2/src/facade/dom';
|
||||||
import {ListWrapper, MapWrapper} from 'angular2/src/facade/collection';
|
import {ListWrapper, MapWrapper} from 'angular2/src/facade/collection';
|
||||||
import {Injector} from 'angular2/di';
|
import {Injector} from 'angular2/di';
|
||||||
import {ProtoElementInjector, ElementInjector} from 'angular2/src/core/compiler/element_injector';
|
import {ProtoElementInjector, ElementInjector} from 'angular2/src/core/compiler/element_injector';
|
||||||
|
import {NativeShadowDomStrategy} from 'angular2/src/core/compiler/shadow_dom_strategy';
|
||||||
import {DynamicProtoChangeDetector, ChangeDetector, Lexer, Parser} from 'angular2/change_detection';
|
import {DynamicProtoChangeDetector, ChangeDetector, Lexer, Parser} from 'angular2/change_detection';
|
||||||
|
|
||||||
function createView(nodes) {
|
function createView(nodes) {
|
||||||
|
@ -68,7 +69,7 @@ export function main() {
|
||||||
dom = el(`<div><stuff></stuff><div insert-after-me></div><stuff></stuff></div>`);
|
dom = el(`<div><stuff></stuff><div insert-after-me></div><stuff></stuff></div>`);
|
||||||
var insertionElement = dom.childNodes[1];
|
var insertionElement = dom.childNodes[1];
|
||||||
parentView = createView([dom.childNodes[0]]);
|
parentView = createView([dom.childNodes[0]]);
|
||||||
protoView = new ProtoView(el('<div>hi</div>'), new DynamicProtoChangeDetector());
|
protoView = new ProtoView(el('<div>hi</div>'), new DynamicProtoChangeDetector(), new NativeShadowDomStrategy());
|
||||||
elementInjector = new ElementInjector(null, null, null, null);
|
elementInjector = new ElementInjector(null, null, null, null);
|
||||||
viewPort = new ViewPort(parentView, insertionElement, protoView, elementInjector);
|
viewPort = new ViewPort(parentView, insertionElement, protoView, elementInjector);
|
||||||
customViewWithOneNode = createView([el('<div>single</div>')]);
|
customViewWithOneNode = createView([el('<div>single</div>')]);
|
||||||
|
@ -212,7 +213,7 @@ export function main() {
|
||||||
viewPort.hydrate(new Injector([]), null);
|
viewPort.hydrate(new Injector([]), null);
|
||||||
|
|
||||||
var pv = new ProtoView(el('<div class="ng-binding">{{}}</div>'),
|
var pv = new ProtoView(el('<div class="ng-binding">{{}}</div>'),
|
||||||
new DynamicProtoChangeDetector());
|
new DynamicProtoChangeDetector(), new NativeShadowDomStrategy());
|
||||||
pv.bindElement(new ProtoElementInjector(null, 1, [SomeDirective]));
|
pv.bindElement(new ProtoElementInjector(null, 1, [SomeDirective]));
|
||||||
pv.bindTextNode(0, parser.parseBinding('foo', null));
|
pv.bindTextNode(0, parser.parseBinding('foo', null));
|
||||||
fancyView = pv.instantiate(null);
|
fancyView = pv.instantiate(null);
|
||||||
|
|
|
@ -7,6 +7,7 @@ import {Lexer, Parser, ChangeDetector, dynamicChangeDetection} from 'angular2/ch
|
||||||
|
|
||||||
import {Compiler, CompilerCache} from 'angular2/src/core/compiler/compiler';
|
import {Compiler, CompilerCache} from 'angular2/src/core/compiler/compiler';
|
||||||
import {DirectiveMetadataReader} from 'angular2/src/core/compiler/directive_metadata_reader';
|
import {DirectiveMetadataReader} from 'angular2/src/core/compiler/directive_metadata_reader';
|
||||||
|
import {NativeShadowDomStrategy} from 'angular2/src/core/compiler/shadow_dom_strategy';
|
||||||
|
|
||||||
import {Component} from 'angular2/src/core/annotations/annotations';
|
import {Component} from 'angular2/src/core/annotations/annotations';
|
||||||
import {TemplateConfig} from 'angular2/src/core/annotations/template_config';
|
import {TemplateConfig} from 'angular2/src/core/annotations/template_config';
|
||||||
|
@ -17,8 +18,13 @@ export function main() {
|
||||||
describe('ng-if', () => {
|
describe('ng-if', () => {
|
||||||
var view, cd, compiler, component;
|
var view, cd, compiler, component;
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
compiler = new Compiler(dynamicChangeDetection, null, new DirectiveMetadataReader(),
|
compiler = new Compiler(
|
||||||
new Parser(new Lexer()), new CompilerCache());
|
dynamicChangeDetection,
|
||||||
|
null,
|
||||||
|
new DirectiveMetadataReader(),
|
||||||
|
new Parser(new Lexer()),
|
||||||
|
new CompilerCache(),
|
||||||
|
new NativeShadowDomStrategy());
|
||||||
});
|
});
|
||||||
|
|
||||||
function createView(pv) {
|
function createView(pv) {
|
||||||
|
|
|
@ -4,6 +4,7 @@ import {Injector} from 'angular2/di';
|
||||||
import {Lexer, Parser, ChangeDetector, dynamicChangeDetection} from 'angular2/change_detection';
|
import {Lexer, Parser, ChangeDetector, dynamicChangeDetection} from 'angular2/change_detection';
|
||||||
import {Compiler, CompilerCache} from 'angular2/src/core/compiler/compiler';
|
import {Compiler, CompilerCache} from 'angular2/src/core/compiler/compiler';
|
||||||
import {DirectiveMetadataReader} from 'angular2/src/core/compiler/directive_metadata_reader';
|
import {DirectiveMetadataReader} from 'angular2/src/core/compiler/directive_metadata_reader';
|
||||||
|
import {NativeShadowDomStrategy} from 'angular2/src/core/compiler/shadow_dom_strategy';
|
||||||
import {Decorator, Component} from 'angular2/src/core/annotations/annotations';
|
import {Decorator, Component} from 'angular2/src/core/annotations/annotations';
|
||||||
import {TemplateConfig} from 'angular2/src/core/annotations/template_config';
|
import {TemplateConfig} from 'angular2/src/core/annotations/template_config';
|
||||||
import {NgElement} from 'angular2/src/core/dom/element';
|
import {NgElement} from 'angular2/src/core/dom/element';
|
||||||
|
@ -13,8 +14,14 @@ export function main() {
|
||||||
describe('ng-non-bindable', () => {
|
describe('ng-non-bindable', () => {
|
||||||
var view, cd, compiler, component;
|
var view, cd, compiler, component;
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
compiler = new Compiler(dynamicChangeDetection,
|
compiler = new Compiler(
|
||||||
null, new DirectiveMetadataReader(), new Parser(new Lexer()), new CompilerCache());
|
dynamicChangeDetection,
|
||||||
|
null,
|
||||||
|
new DirectiveMetadataReader(),
|
||||||
|
new Parser(new Lexer()),
|
||||||
|
new CompilerCache(),
|
||||||
|
new NativeShadowDomStrategy()
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
function createView(pv) {
|
function createView(pv) {
|
||||||
|
|
|
@ -8,6 +8,7 @@ import {Lexer, Parser, ChangeDetector, dynamicChangeDetection} from 'angular2/ch
|
||||||
import {Compiler, CompilerCache} from 'angular2/src/core/compiler/compiler';
|
import {Compiler, CompilerCache} from 'angular2/src/core/compiler/compiler';
|
||||||
import {OnChange} from 'angular2/src/core/compiler/interfaces';
|
import {OnChange} from 'angular2/src/core/compiler/interfaces';
|
||||||
import {DirectiveMetadataReader} from 'angular2/src/core/compiler/directive_metadata_reader';
|
import {DirectiveMetadataReader} from 'angular2/src/core/compiler/directive_metadata_reader';
|
||||||
|
import {NativeShadowDomStrategy} from 'angular2/src/core/compiler/shadow_dom_strategy';
|
||||||
|
|
||||||
import {Decorator, Component, Template} from 'angular2/src/core/annotations/annotations';
|
import {Decorator, Component, Template} from 'angular2/src/core/annotations/annotations';
|
||||||
import {TemplateConfig} from 'angular2/src/core/annotations/template_config';
|
import {TemplateConfig} from 'angular2/src/core/annotations/template_config';
|
||||||
|
@ -20,8 +21,14 @@ export function main() {
|
||||||
describe('ng-repeat', () => {
|
describe('ng-repeat', () => {
|
||||||
var view, cd, compiler, component;
|
var view, cd, compiler, component;
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
compiler = new Compiler(dynamicChangeDetection, null, new DirectiveMetadataReader(),
|
compiler = new Compiler(
|
||||||
new Parser(new Lexer()), new CompilerCache());
|
dynamicChangeDetection,
|
||||||
|
null,
|
||||||
|
new DirectiveMetadataReader(),
|
||||||
|
new Parser(new Lexer()),
|
||||||
|
new CompilerCache(),
|
||||||
|
new NativeShadowDomStrategy()
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
function createView(pv) {
|
function createView(pv) {
|
||||||
|
|
|
@ -4,6 +4,7 @@ import {Injector} from 'angular2/di';
|
||||||
import {Lexer, Parser, dynamicChangeDetection} from 'angular2/change_detection';
|
import {Lexer, Parser, dynamicChangeDetection} from 'angular2/change_detection';
|
||||||
import {Compiler, CompilerCache} from 'angular2/src/core/compiler/compiler';
|
import {Compiler, CompilerCache} from 'angular2/src/core/compiler/compiler';
|
||||||
import {DirectiveMetadataReader} from 'angular2/src/core/compiler/directive_metadata_reader';
|
import {DirectiveMetadataReader} from 'angular2/src/core/compiler/directive_metadata_reader';
|
||||||
|
import {NativeShadowDomStrategy} from 'angular2/src/core/compiler/shadow_dom_strategy';
|
||||||
import {Component} from 'angular2/src/core/annotations/annotations';
|
import {Component} from 'angular2/src/core/annotations/annotations';
|
||||||
import {TemplateConfig} from 'angular2/src/core/annotations/template_config';
|
import {TemplateConfig} from 'angular2/src/core/annotations/template_config';
|
||||||
import {NgSwitch, NgSwitchWhen, NgSwitchDefault} from 'angular2/src/directives/ng_switch';
|
import {NgSwitch, NgSwitchWhen, NgSwitchDefault} from 'angular2/src/directives/ng_switch';
|
||||||
|
@ -12,8 +13,14 @@ export function main() {
|
||||||
describe('ng-switch', () => {
|
describe('ng-switch', () => {
|
||||||
var view, cd, compiler, component;
|
var view, cd, compiler, component;
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
compiler = new Compiler(dynamicChangeDetection, null, new DirectiveMetadataReader(),
|
compiler = new Compiler(
|
||||||
new Parser(new Lexer()), new CompilerCache());
|
dynamicChangeDetection,
|
||||||
|
null,
|
||||||
|
new DirectiveMetadataReader(),
|
||||||
|
new Parser(new Lexer()),
|
||||||
|
new CompilerCache(),
|
||||||
|
new NativeShadowDomStrategy()
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
function createView(pv) {
|
function createView(pv) {
|
||||||
|
|
|
@ -4,6 +4,7 @@ import {ddescribe, describe, it, iit, xit, expect, beforeEach, afterEach,
|
||||||
import {Lexer, Parser, ChangeDetector, dynamicChangeDetection} from 'angular2/change_detection';
|
import {Lexer, Parser, ChangeDetector, dynamicChangeDetection} from 'angular2/change_detection';
|
||||||
import {Compiler, CompilerCache} from 'angular2/src/core/compiler/compiler';
|
import {Compiler, CompilerCache} from 'angular2/src/core/compiler/compiler';
|
||||||
import {DirectiveMetadataReader} from 'angular2/src/core/compiler/directive_metadata_reader';
|
import {DirectiveMetadataReader} from 'angular2/src/core/compiler/directive_metadata_reader';
|
||||||
|
import {NativeShadowDomStrategy} from 'angular2/src/core/compiler/shadow_dom_strategy';
|
||||||
import {Injector} from 'angular2/di';
|
import {Injector} from 'angular2/di';
|
||||||
import {DOM} from 'angular2/src/facade/dom';
|
import {DOM} from 'angular2/src/facade/dom';
|
||||||
|
|
||||||
|
@ -17,7 +18,7 @@ export function main() {
|
||||||
|
|
||||||
function compile(componentType, template, context, callback) {
|
function compile(componentType, template, context, callback) {
|
||||||
var compiler = new Compiler(dynamicChangeDetection, null, new DirectiveMetadataReader(),
|
var compiler = new Compiler(dynamicChangeDetection, null, new DirectiveMetadataReader(),
|
||||||
new Parser(new Lexer()), new CompilerCache());
|
new Parser(new Lexer()), new CompilerCache(), new NativeShadowDomStrategy());
|
||||||
|
|
||||||
compiler.compile(componentType, el(template)).then((pv) => {
|
compiler.compile(componentType, el(template)).then((pv) => {
|
||||||
var view = pv.instantiate(null);
|
var view = pv.instantiate(null);
|
||||||
|
|
|
@ -0,0 +1,111 @@
|
||||||
|
import {describe, beforeEach, it, expect, ddescribe, iit, el, IS_DARTIUM} from 'angular2/test_lib';
|
||||||
|
import {XHRMock} from 'angular2/src/mock/xhr_mock';
|
||||||
|
import {PromiseWrapper, Promise} from 'angular2/src/facade/async';
|
||||||
|
import {isPresent} from 'angular2/src/facade/lang';
|
||||||
|
import {ListWrapper} from 'angular2/src/facade/collection';
|
||||||
|
|
||||||
|
export function main() {
|
||||||
|
describe('XHRMock', () => {
|
||||||
|
var xhr;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
xhr = new XHRMock();
|
||||||
|
});
|
||||||
|
|
||||||
|
function expectResponse(request: Promise, url: string, response: string, done = null) {
|
||||||
|
function onResponse(text: string) {
|
||||||
|
if (response === null) {
|
||||||
|
throw `Unexpected response ${url} -> ${text}`;
|
||||||
|
} else {
|
||||||
|
expect(text).toEqual(response);
|
||||||
|
if (isPresent(done)) done();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onError(error: string) {
|
||||||
|
if (response !== null) {
|
||||||
|
throw `Unexpected error ${url}`;
|
||||||
|
} else {
|
||||||
|
expect(error).toEqual(`Failed to load ${url}`);
|
||||||
|
if (isPresent(done)) done();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PromiseWrapper.then(request, onResponse, onError);
|
||||||
|
}
|
||||||
|
|
||||||
|
it('should return a response from the definitions', (done) => {
|
||||||
|
var url = '/foo';
|
||||||
|
var response = 'bar';
|
||||||
|
xhr.when(url, response);
|
||||||
|
expectResponse(xhr.get(url), url, response, done);
|
||||||
|
xhr.flush();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return an error from the definitions', (done) => {
|
||||||
|
var url = '/foo';
|
||||||
|
var response = null;
|
||||||
|
xhr.when(url, response);
|
||||||
|
expectResponse(xhr.get(url), url, response, done);
|
||||||
|
xhr.flush();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return a response from the expectations', (done) => {
|
||||||
|
var url = '/foo';
|
||||||
|
var response = 'bar';
|
||||||
|
xhr.expect(url, response);
|
||||||
|
expectResponse(xhr.get(url), url, response, done);
|
||||||
|
xhr.flush();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return an error from the expectations', (done) => {
|
||||||
|
var url = '/foo';
|
||||||
|
var response = null;
|
||||||
|
xhr.expect(url, response);
|
||||||
|
expectResponse(xhr.get(url), url, response, done);
|
||||||
|
xhr.flush();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not reuse expectations', () => {
|
||||||
|
var url = '/foo';
|
||||||
|
var response = 'bar';
|
||||||
|
xhr.expect(url, response);
|
||||||
|
xhr.get(url);
|
||||||
|
xhr.get(url);
|
||||||
|
expect(() => {
|
||||||
|
xhr.flush();
|
||||||
|
}).toThrowError('Unexpected request /foo');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return expectations before definitions', (done) => {
|
||||||
|
var url = '/foo';
|
||||||
|
xhr.when(url, 'when');
|
||||||
|
xhr.expect(url, 'expect');
|
||||||
|
expectResponse(xhr.get(url), url, 'expect');
|
||||||
|
expectResponse(xhr.get(url), url, 'when', done);
|
||||||
|
xhr.flush();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw when there is no definitions or expectations', () => {
|
||||||
|
xhr.get('/foo');
|
||||||
|
expect(() => {
|
||||||
|
xhr.flush();
|
||||||
|
}).toThrowError('Unexpected request /foo');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw when flush is called without any pending requests', () => {
|
||||||
|
expect(() => {
|
||||||
|
xhr.flush();
|
||||||
|
}).toThrowError('No pending requests to flush');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw on unstatisfied expectations', () => {
|
||||||
|
xhr.expect('/foo', 'bar');
|
||||||
|
xhr.when('/bar', 'foo');
|
||||||
|
xhr.get('/bar');
|
||||||
|
expect(() => {
|
||||||
|
xhr.flush();
|
||||||
|
}).toThrowError('Unsatisfied requests: /foo');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
|
@ -7,24 +7,30 @@ describe('ng2 compiler benchmark', function () {
|
||||||
afterEach(perfUtil.verifyNoBrowserErrors);
|
afterEach(perfUtil.verifyNoBrowserErrors);
|
||||||
|
|
||||||
it('should log withBindings stats', function() {
|
it('should log withBindings stats', function() {
|
||||||
perfUtil.runClickBenchmark({
|
perfUtil.runBenchmark({
|
||||||
url: URL,
|
url: URL,
|
||||||
buttons: ['#compileWithBindings'],
|
|
||||||
id: 'ng2.compile.withBindings',
|
id: 'ng2.compile.withBindings',
|
||||||
params: [{
|
params: [{
|
||||||
name: 'elements', value: 150, scale: 'linear'
|
name: 'elements', value: 150, scale: 'linear'
|
||||||
}]
|
}],
|
||||||
|
work: function() {
|
||||||
|
browser.executeScript('document.querySelector("#compileWithBindings").click()');
|
||||||
|
browser.sleep(500);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should log noBindings stats', function() {
|
it('should log noBindings stats', function() {
|
||||||
perfUtil.runClickBenchmark({
|
perfUtil.runBenchmark({
|
||||||
url: URL,
|
url: URL,
|
||||||
buttons: ['#compileNoBindings'],
|
|
||||||
id: 'ng2.compile.noBindings',
|
id: 'ng2.compile.noBindings',
|
||||||
params: [{
|
params: [{
|
||||||
name: 'elements', value: 150, scale: 'linear'
|
name: 'elements', value: 150, scale: 'linear'
|
||||||
}]
|
}],
|
||||||
|
work: function() {
|
||||||
|
browser.executeScript('document.querySelector("#compileNoBindings").click()');
|
||||||
|
browser.sleep(500);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ import {DOM, document} from 'angular2/src/facade/dom';
|
||||||
import {isBlank, Type} from 'angular2/src/facade/lang';
|
import {isBlank, Type} from 'angular2/src/facade/lang';
|
||||||
import {MapWrapper} from 'angular2/src/facade/collection';
|
import {MapWrapper} from 'angular2/src/facade/collection';
|
||||||
import {DirectiveMetadata} from 'angular2/src/core/compiler/directive_metadata';
|
import {DirectiveMetadata} from 'angular2/src/core/compiler/directive_metadata';
|
||||||
|
import {NativeShadowDomStrategy} from 'angular2/src/core/compiler/shadow_dom_strategy';
|
||||||
|
|
||||||
import {Parser, Lexer, ProtoRecordRange, dynamicChangeDetection} from 'angular2/change_detection';
|
import {Parser, Lexer, ProtoRecordRange, dynamicChangeDetection} from 'angular2/change_detection';
|
||||||
|
|
||||||
|
@ -11,10 +12,13 @@ import {DirectiveMetadataReader} from 'angular2/src/core/compiler/directive_meta
|
||||||
import {Component} from 'angular2/src/core/annotations/annotations';
|
import {Component} from 'angular2/src/core/annotations/annotations';
|
||||||
import {Decorator} from 'angular2/src/core/annotations/annotations';
|
import {Decorator} from 'angular2/src/core/annotations/annotations';
|
||||||
import {TemplateConfig} from 'angular2/src/core/annotations/template_config';
|
import {TemplateConfig} from 'angular2/src/core/annotations/template_config';
|
||||||
|
import {TemplateLoader} from 'angular2/src/core/compiler/template_loader';
|
||||||
|
|
||||||
import {reflector} from 'angular2/src/reflection/reflection';
|
import {reflector} from 'angular2/src/reflection/reflection';
|
||||||
import {getIntParameter, bindAction} from 'angular2/src/test_lib/benchmark_util';
|
import {getIntParameter, bindAction} from 'angular2/src/test_lib/benchmark_util';
|
||||||
|
|
||||||
|
import {XHRImpl} from 'angular2/src/core/compiler/xhr/xhr_impl';
|
||||||
|
|
||||||
function setupReflector() {
|
function setupReflector() {
|
||||||
reflector.registerType(BenchmarkComponent, {
|
reflector.registerType(BenchmarkComponent, {
|
||||||
"factory": () => new BenchmarkComponent(),
|
"factory": () => new BenchmarkComponent(),
|
||||||
|
@ -79,9 +83,8 @@ export function main() {
|
||||||
setupReflector();
|
setupReflector();
|
||||||
var reader = new DirectiveMetadataReader();
|
var reader = new DirectiveMetadataReader();
|
||||||
var cache = new CompilerCache();
|
var cache = new CompilerCache();
|
||||||
var compiler = new Compiler(dynamicChangeDetection, null, reader, new Parser(new Lexer()), cache);
|
var compiler = new Compiler(dynamicChangeDetection, new TemplateLoader(new XHRImpl()),
|
||||||
var annotatedComponent = reader.read(BenchmarkComponent);
|
reader, new Parser(new Lexer()), cache, new NativeShadowDomStrategy());
|
||||||
|
|
||||||
var templateNoBindings = loadTemplate('templateNoBindings', count);
|
var templateNoBindings = loadTemplate('templateNoBindings', count);
|
||||||
var templateWithBindings = loadTemplate('templateWithBindings', count);
|
var templateWithBindings = loadTemplate('templateWithBindings', count);
|
||||||
|
|
||||||
|
@ -89,14 +92,14 @@ export function main() {
|
||||||
// Need to clone every time as the compiler might modify the template!
|
// Need to clone every time as the compiler might modify the template!
|
||||||
var cloned = DOM.clone(templateNoBindings);
|
var cloned = DOM.clone(templateNoBindings);
|
||||||
cache.clear();
|
cache.clear();
|
||||||
compiler.compileAllLoaded(null, annotatedComponent, cloned);
|
compiler.compile(BenchmarkComponent, cloned);
|
||||||
}
|
}
|
||||||
|
|
||||||
function compileWithBindings() {
|
function compileWithBindings() {
|
||||||
// Need to clone every time as the compiler might modify the template!
|
// Need to clone every time as the compiler might modify the template!
|
||||||
var cloned = DOM.clone(templateWithBindings);
|
var cloned = DOM.clone(templateWithBindings);
|
||||||
cache.clear();
|
cache.clear();
|
||||||
compiler.compileAllLoaded(null, annotatedComponent, cloned);
|
compiler.compile(BenchmarkComponent, cloned);
|
||||||
}
|
}
|
||||||
|
|
||||||
bindAction('#compileNoBindings', compileNoBindings);
|
bindAction('#compileNoBindings', compileNoBindings);
|
||||||
|
|
|
@ -6,6 +6,7 @@ import {bootstrap, Component, Template, TemplateConfig, ViewPort, Compiler} from
|
||||||
import {CompilerCache} from 'angular2/src/core/compiler/compiler';
|
import {CompilerCache} from 'angular2/src/core/compiler/compiler';
|
||||||
import {DirectiveMetadataReader} from 'angular2/src/core/compiler/directive_metadata_reader';
|
import {DirectiveMetadataReader} from 'angular2/src/core/compiler/directive_metadata_reader';
|
||||||
import {TemplateLoader} from 'angular2/src/core/compiler/template_loader';
|
import {TemplateLoader} from 'angular2/src/core/compiler/template_loader';
|
||||||
|
import {ShadowDomStrategy, NativeShadowDomStrategy} from 'angular2/src/core/compiler/shadow_dom_strategy';
|
||||||
import {LifeCycle} from 'angular2/src/core/life_cycle/life_cycle';
|
import {LifeCycle} from 'angular2/src/core/life_cycle/life_cycle';
|
||||||
|
|
||||||
import {reflector} from 'angular2/src/reflection/reflection';
|
import {reflector} from 'angular2/src/reflection/reflection';
|
||||||
|
@ -13,6 +14,9 @@ import {DOM, document, window, Element, gc} from 'angular2/src/facade/dom';
|
||||||
import {isPresent} from 'angular2/src/facade/lang';
|
import {isPresent} from 'angular2/src/facade/lang';
|
||||||
import {getIntParameter, bindAction} from 'angular2/src/test_lib/benchmark_util';
|
import {getIntParameter, bindAction} from 'angular2/src/test_lib/benchmark_util';
|
||||||
|
|
||||||
|
import {XHR} from 'angular2/src/core/compiler/xhr/xhr';
|
||||||
|
import {XHRImpl} from 'angular2/src/core/compiler/xhr/xhr_impl';
|
||||||
|
|
||||||
function setupReflector() {
|
function setupReflector() {
|
||||||
// TODO: Put the general calls to reflector.register... in a shared file
|
// TODO: Put the general calls to reflector.register... in a shared file
|
||||||
// as they are needed in all benchmarks...
|
// as they are needed in all benchmarks...
|
||||||
|
@ -56,8 +60,10 @@ function setupReflector() {
|
||||||
});
|
});
|
||||||
|
|
||||||
reflector.registerType(Compiler, {
|
reflector.registerType(Compiler, {
|
||||||
'factory': (cd, templateLoader, reader, parser, compilerCache) => new Compiler(cd, templateLoader, reader, parser, compilerCache),
|
'factory': (cd, templateLoader, reader, parser, compilerCache, strategy)
|
||||||
'parameters': [[ChangeDetection], [TemplateLoader], [DirectiveMetadataReader], [Parser], [CompilerCache]],
|
=> new Compiler(cd, templateLoader, reader, parser, compilerCache, strategy),
|
||||||
|
'parameters': [[ChangeDetection], [TemplateLoader], [DirectiveMetadataReader],
|
||||||
|
[Parser], [CompilerCache], [ShadowDomStrategy]],
|
||||||
'annotations': []
|
'annotations': []
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -74,7 +80,13 @@ function setupReflector() {
|
||||||
});
|
});
|
||||||
|
|
||||||
reflector.registerType(TemplateLoader, {
|
reflector.registerType(TemplateLoader, {
|
||||||
'factory': () => new TemplateLoader(),
|
'factory': (xhr) => new TemplateLoader(xhr),
|
||||||
|
'parameters': [[XHR]],
|
||||||
|
'annotations': []
|
||||||
|
});
|
||||||
|
|
||||||
|
reflector.registerType(XHR, {
|
||||||
|
'factory': () => new XHRImpl(),
|
||||||
'parameters': [],
|
'parameters': [],
|
||||||
'annotations': []
|
'annotations': []
|
||||||
});
|
});
|
||||||
|
@ -85,6 +97,12 @@ function setupReflector() {
|
||||||
'annotations': []
|
'annotations': []
|
||||||
});
|
});
|
||||||
|
|
||||||
|
reflector.registerType(ShadowDomStrategy, {
|
||||||
|
'factory': () => new NativeShadowDomStrategy(),
|
||||||
|
'parameters': [],
|
||||||
|
'annotations': []
|
||||||
|
});
|
||||||
|
|
||||||
reflector.registerType(Lexer, {
|
reflector.registerType(Lexer, {
|
||||||
'factory': () => new Lexer(),
|
'factory': () => new Lexer(),
|
||||||
'parameters': [],
|
'parameters': [],
|
||||||
|
|
|
@ -6,7 +6,10 @@ import {LifeCycle} from 'angular2/src/core/life_cycle/life_cycle';
|
||||||
|
|
||||||
import {Compiler, CompilerCache} from 'angular2/src/core/compiler/compiler';
|
import {Compiler, CompilerCache} from 'angular2/src/core/compiler/compiler';
|
||||||
import {DirectiveMetadataReader} from 'angular2/src/core/compiler/directive_metadata_reader';
|
import {DirectiveMetadataReader} from 'angular2/src/core/compiler/directive_metadata_reader';
|
||||||
|
import {ShadowDomStrategy, NativeShadowDomStrategy} from 'angular2/src/core/compiler/shadow_dom_strategy';
|
||||||
import {TemplateLoader} from 'angular2/src/core/compiler/template_loader';
|
import {TemplateLoader} from 'angular2/src/core/compiler/template_loader';
|
||||||
|
import {XHR} from 'angular2/src/core/compiler/xhr/xhr';
|
||||||
|
import {XHRImpl} from 'angular2/src/core/compiler/xhr/xhr_impl';
|
||||||
|
|
||||||
import {reflector} from 'angular2/src/reflection/reflection';
|
import {reflector} from 'angular2/src/reflection/reflection';
|
||||||
|
|
||||||
|
@ -37,8 +40,10 @@ function setup() {
|
||||||
});
|
});
|
||||||
|
|
||||||
reflector.registerType(Compiler, {
|
reflector.registerType(Compiler, {
|
||||||
"factory": (changeDetection, templateLoader, reader, parser, compilerCache) => new Compiler(changeDetection, templateLoader, reader, parser, compilerCache),
|
"factory": (changeDetection, templateLoader, reader, parser, compilerCache, shadowDomStrategy) =>
|
||||||
"parameters": [[ChangeDetection], [TemplateLoader], [DirectiveMetadataReader], [Parser], [CompilerCache]],
|
new Compiler(changeDetection, templateLoader, reader, parser, compilerCache, shadowDomStrategy),
|
||||||
|
"parameters": [[ChangeDetection], [TemplateLoader], [DirectiveMetadataReader], [Parser],
|
||||||
|
[CompilerCache], [ShadowDomStrategy]],
|
||||||
"annotations": []
|
"annotations": []
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -55,7 +60,13 @@ function setup() {
|
||||||
});
|
});
|
||||||
|
|
||||||
reflector.registerType(TemplateLoader, {
|
reflector.registerType(TemplateLoader, {
|
||||||
"factory": () => new TemplateLoader(),
|
"factory": (xhr) => new TemplateLoader(xhr),
|
||||||
|
"parameters": [[XHR]],
|
||||||
|
"annotations": []
|
||||||
|
});
|
||||||
|
|
||||||
|
reflector.registerType(XHR, {
|
||||||
|
"factory": () => new XHRImpl(),
|
||||||
"parameters": [],
|
"parameters": [],
|
||||||
"annotations": []
|
"annotations": []
|
||||||
});
|
});
|
||||||
|
@ -78,6 +89,12 @@ function setup() {
|
||||||
"annotations": []
|
"annotations": []
|
||||||
});
|
});
|
||||||
|
|
||||||
|
reflector.registerType(ShadowDomStrategy, {
|
||||||
|
"factory": () => new NativeShadowDomStrategy(),
|
||||||
|
"parameters": [],
|
||||||
|
"annotations": []
|
||||||
|
});
|
||||||
|
|
||||||
reflector.registerGetters({
|
reflector.registerGetters({
|
||||||
"greeting": (a) => a.greeting
|
"greeting": (a) => a.greeting
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue