refactor(Compiler): inline styles before compiling the template

This commit is contained in:
Victor Berchet 2015-06-15 15:57:42 +02:00
parent 3875f02a52
commit 3ea655918e
30 changed files with 288 additions and 468 deletions

View File

@ -25,6 +25,8 @@ import {
} from 'angular2/change_detection';
import {ExceptionHandler} from './exception_handler';
import {TemplateLoader} from 'angular2/src/render/dom/compiler/template_loader';
import {StyleUrlResolver} from 'angular2/src/render/dom/compiler/style_url_resolver';
import {StyleInliner} from 'angular2/src/render/dom/compiler/style_inliner';
import {TemplateResolver} from './compiler/template_resolver';
import {DirectiveResolver} from './compiler/directive_resolver';
import {List, ListWrapper} from 'angular2/src/facade/collection';
@ -42,8 +44,6 @@ import {KeyEventsPlugin} from 'angular2/src/render/dom/events/key_events';
import {HammerGesturesPlugin} from 'angular2/src/render/dom/events/hammer_gestures';
import {ComponentUrlMapper} from 'angular2/src/core/compiler/component_url_mapper';
import {UrlResolver} from 'angular2/src/services/url_resolver';
import {StyleUrlResolver} from 'angular2/src/render/dom/shadow_dom/style_url_resolver';
import {StyleInliner} from 'angular2/src/render/dom/shadow_dom/style_inliner';
import {AppRootUrl} from 'angular2/src/services/app_root_url';
import {
ComponentRef,
@ -105,9 +105,7 @@ function _injectorBindings(appComponentType): List<Type | Binding | List<any>> {
},
[NgZone]),
bind(ShadowDomStrategy)
.toFactory((styleInliner, styleUrlResolver, doc) => new EmulatedUnscopedShadowDomStrategy(
styleInliner, styleUrlResolver, doc.head),
[StyleInliner, StyleUrlResolver, DOCUMENT_TOKEN]),
.toFactory((doc) => new EmulatedUnscopedShadowDomStrategy(doc.head), [DOCUMENT_TOKEN]),
DomRenderer,
DefaultDomCompiler,
bind(Renderer).toAlias(DomRenderer),

View File

@ -22,7 +22,7 @@ export class TemplateResolver {
return view;
}
_resolve(component: Type) {
_resolve(component: Type): View {
var annotations = reflector.annotations(component);
for (var i = 0; i < annotations.length; i++) {
var annotation = annotations[i];

View File

@ -67,10 +67,10 @@ class Html5LibDomAdapter implements DomAdapter {
throw 'not implemented';
}
querySelector(el, String selector) {
throw 'not implemented';
return el.querySelector(selector);
}
List querySelectorAll(el, String selector) {
throw 'not implemented';
return el.querySelectorAll(selector);
}
on(el, evt, listener) {
throw 'not implemented';
@ -94,7 +94,7 @@ class Html5LibDomAdapter implements DomAdapter {
return el.innerHtml;
}
getOuterHTML(el) {
throw 'not implemented';
return el.outerHtml;
}
String nodeName(node) {
switch (node.nodeType) {
@ -130,12 +130,12 @@ class Html5LibDomAdapter implements DomAdapter {
}
parentElement(el) {
throw 'not implemented';
return el.parent;
}
List childNodes(el) => el.nodes;
List childNodesAsList(el) => el.nodes;
clearNodes(el) {
throw 'not implemented';
el.nodes.forEach((e) => e.remove());
}
appendChild(el, node) => el.append(node.remove());
removeChild(el, node) {
@ -153,7 +153,7 @@ class Html5LibDomAdapter implements DomAdapter {
throw 'not implemented';
}
setInnerHTML(el, value) {
throw 'not implemented';
el.innerHtml = value;
}
getText(el) {
return el.text;

View File

@ -303,7 +303,7 @@ export class RenderCompiler {
* we don't need to serialize all possible components over the wire,
* but only the needed ones based on previous calls.
*/
compile(template: ViewDefinition): Promise<ProtoViewDto> { return null; }
compile(view: ViewDefinition): Promise<ProtoViewDto> { return null; }
}
export interface RenderElementRef {

View File

@ -1,6 +1,4 @@
import {List} from 'angular2/src/facade/collection';
import {Promise} from 'angular2/src/facade/async';
import {Parser} from 'angular2/change_detection';
import {ViewDefinition} from '../../api';
import {CompileStep} from './compile_step';
@ -12,21 +10,19 @@ import {ShadowDomCompileStep} from '../shadow_dom/shadow_dom_compile_step';
import {ShadowDomStrategy} from '../shadow_dom/shadow_dom_strategy';
export class CompileStepFactory {
createSteps(template: ViewDefinition, subTaskPromises: List<Promise<any>>): List<CompileStep> {
return null;
}
createSteps(template: ViewDefinition): List<CompileStep> { return null; }
}
export class DefaultStepFactory extends CompileStepFactory {
constructor(public _parser: Parser, public _shadowDomStrategy: ShadowDomStrategy) { super(); }
createSteps(template: ViewDefinition, subTaskPromises: List<Promise<any>>) {
createSteps(template: ViewDefinition): List<CompileStep> {
return [
new ViewSplitter(this._parser),
new PropertyBindingParser(this._parser),
new DirectiveParser(this._parser, template.directives),
new TextInterpolationParser(this._parser),
new ShadowDomCompileStep(this._shadowDomStrategy, template, subTaskPromises)
new ShadowDomCompileStep(this._shadowDomStrategy, template)
];
}
}

View File

@ -28,12 +28,11 @@ export class DomCompiler extends RenderCompiler {
super();
}
compile(template: ViewDefinition): Promise<ProtoViewDto> {
var tplPromise = this._templateLoader.load(template);
compile(view: ViewDefinition): Promise<ProtoViewDto> {
var tplPromise = this._templateLoader.load(view);
return PromiseWrapper.then(
tplPromise, (el) => this._compileTemplate(template, el, ViewType.COMPONENT), (e) => {
throw new BaseException(
`Failed to load the template for "${template.componentId}" : ${e}`);
tplPromise, (el) => this._compileTemplate(view, el, ViewType.COMPONENT), (e) => {
throw new BaseException(`Failed to load the template for "${view.componentId}" : ${e}`);
});
}
@ -51,17 +50,10 @@ export class DomCompiler extends RenderCompiler {
_compileTemplate(viewDef: ViewDefinition, tplElement,
protoViewType: ViewType): Promise<ProtoViewDto> {
var subTaskPromises = [];
var pipeline = new CompilePipeline(this._stepFactory.createSteps(viewDef, subTaskPromises));
var pipeline = new CompilePipeline(this._stepFactory.createSteps(viewDef));
var compileElements = pipeline.process(tplElement, protoViewType, viewDef.componentId);
var protoView = compileElements[0].inheritedProtoView.build();
if (subTaskPromises.length > 0) {
return PromiseWrapper.all(subTaskPromises).then((_) => protoView);
} else {
return PromiseWrapper.resolve(protoView);
}
return PromiseWrapper.resolve(compileElements[0].inheritedProtoView.build());
}
}

View File

@ -1,13 +1,15 @@
import {Injectable} from 'angular2/di';
import {isBlank, isPresent, BaseException, stringify} from 'angular2/src/facade/lang';
import {Map, MapWrapper, ListWrapper} from 'angular2/src/facade/collection';
import {isBlank, isPresent, BaseException, stringify, isPromise} from 'angular2/src/facade/lang';
import {Map, MapWrapper, ListWrapper, List} from 'angular2/src/facade/collection';
import {PromiseWrapper, Promise} from 'angular2/src/facade/async';
import {DOM} from 'angular2/src/dom/dom_adapter';
import {XHR} from 'angular2/src/render/xhr';
import {ViewDefinition} from '../../api';
import {UrlResolver} from 'angular2/src/services/url_resolver';
import {StyleInliner} from './style_inliner';
import {StyleUrlResolver} from './style_url_resolver';
/**
* Strategy to load component templates.
@ -17,37 +19,36 @@ import {UrlResolver} from 'angular2/src/services/url_resolver';
export class TemplateLoader {
_cache: Map<string, Promise<string>> = new Map();
constructor(private _xhr: XHR, urlResolver: UrlResolver) {}
constructor(private _xhr: XHR, private _styleInliner: StyleInliner,
private _styleUrlResolver: StyleUrlResolver) {}
load(view: ViewDefinition): Promise</*element*/ any> {
let html;
let fetchedStyles;
let tplElAndStyles: List<string | Promise<string>> = [this._loadHtml(view)];
// Load the HTML
if (isPresent(view.template)) {
html = PromiseWrapper.resolve(view.template);
} else if (isPresent(view.templateAbsUrl)) {
html = this._loadText(view.templateAbsUrl);
} else {
throw new BaseException('View should have either the templateUrl or template property set');
if (isPresent(view.styles)) {
view.styles.forEach((cssText: string) => {
let textOrPromise = this._resolveAndInlineCssText(cssText, view.templateAbsUrl);
tplElAndStyles.push(textOrPromise);
});
}
// Load the styles
if (isPresent(view.styleAbsUrls) && view.styleAbsUrls.length > 0) {
fetchedStyles = ListWrapper.map(view.styleAbsUrls, url => this._loadText(url));
} else {
fetchedStyles = [];
if (isPresent(view.styleAbsUrls)) {
view.styleAbsUrls.forEach(url => {
let promise = this._loadText(url).then(
cssText => this._resolveAndInlineCssText(cssText, view.templateAbsUrl));
tplElAndStyles.push(promise);
});
}
// Inline the styles and return a template element
return PromiseWrapper.all(ListWrapper.concat([html], fetchedStyles))
// Inline the styles from the @View annotation and return a template element
return PromiseWrapper.all(tplElAndStyles)
.then((res: List<string>) => {
let html = res[0];
let fetchedStyles = ListWrapper.slice(res, 1);
let tplEl = res[0];
let cssTexts = ListWrapper.slice(res, 1);
html = _createStyleTags(view.styles) + _createStyleTags(fetchedStyles) + html;
_insertCssTexts(DOM.content(tplEl), cssTexts);
return DOM.createTemplate(html);
return tplEl;
});
}
@ -67,10 +68,74 @@ export class TemplateLoader {
return response;
}
// Load the html and inline any style tags
private _loadHtml(view: ViewDefinition): Promise<any /* element */> {
let html;
// Load the HTML
if (isPresent(view.template)) {
html = PromiseWrapper.resolve(view.template);
} else if (isPresent(view.templateAbsUrl)) {
html = this._loadText(view.templateAbsUrl);
} else {
throw new BaseException('View should have either the templateUrl or template property set');
}
// Inline the style tags from the html
return html.then(html => {
var tplEl = DOM.createTemplate(html);
let styleEls = DOM.querySelectorAll(DOM.content(tplEl), 'STYLE');
let promises: List<Promise<string>> = [];
for (let i = 0; i < styleEls.length; i++) {
let promise = this._resolveAndInlineElement(styleEls[i], view.templateAbsUrl);
if (isPromise(promise)) {
promises.push(promise);
}
}
return promises.length > 0 ? PromiseWrapper.all(promises).then(_ => tplEl) : tplEl;
});
}
/**
* Inlines a style element.
*
* @param styleEl The style element
* @param baseUrl The base url
* @returns {Promise<any>} null when no @import rule exist in the css or a Promise
* @private
*/
private _resolveAndInlineElement(styleEl, baseUrl: string): Promise<any> {
let textOrPromise = this._resolveAndInlineCssText(DOM.getText(styleEl), baseUrl);
if (isPromise(textOrPromise)) {
return (<Promise<string>>textOrPromise).then(css => { DOM.setText(styleEl, css); });
} else {
DOM.setText(styleEl, <string>textOrPromise);
return null;
}
}
private _resolveAndInlineCssText(cssText: string, baseUrl: string): string | Promise<string> {
cssText = this._styleUrlResolver.resolveUrls(cssText, baseUrl);
return this._styleInliner.inlineImports(cssText, baseUrl);
}
}
function _createStyleTags(styles?: List<string>): string {
return isBlank(styles) ?
'' :
ListWrapper.map(styles, css => `<style type='text/css'>${css}</style>`).join('');
function _insertCssTexts(element, cssTexts: List<string>): void {
if (cssTexts.length == 0) return;
let insertBefore = DOM.firstChild(element);
for (let i = cssTexts.length - 1; i >= 0; i--) {
let styleEl = DOM.createStyleElement(cssTexts[i]);
if (isPresent(insertBefore)) {
DOM.insertBefore(insertBefore, styleEl);
} else {
DOM.appendChild(element, styleEl);
}
insertBefore = styleEl;
}
}

View File

@ -1,10 +1,7 @@
import {isBlank, isPresent, isPromise} from 'angular2/src/facade/lang';
import {PromiseWrapper, Promise} from 'angular2/src/facade/async';
import {isBlank, isPresent} from 'angular2/src/facade/lang';
import {DOM} from 'angular2/src/dom/dom_adapter';
import {StyleInliner} from 'angular2/src/render/dom/shadow_dom/style_inliner';
import {StyleUrlResolver} from 'angular2/src/render/dom/shadow_dom/style_url_resolver';
import {EmulatedUnscopedShadowDomStrategy} from './emulated_unscoped_shadow_dom_strategy';
import {
getContentAttribute,
@ -27,39 +24,21 @@ import {
* - see `ShadowCss` for more information and limitations.
*/
export class EmulatedScopedShadowDomStrategy extends EmulatedUnscopedShadowDomStrategy {
constructor(styleInliner: StyleInliner, styleUrlResolver: StyleUrlResolver, styleHost) {
super(styleInliner, styleUrlResolver, styleHost);
}
processStyleElement(hostComponentId: string, templateUrl: string, styleEl): Promise<any> {
var cssText = DOM.getText(styleEl);
cssText = this.styleUrlResolver.resolveUrls(cssText, templateUrl);
var inlinedCss = this.styleInliner.inlineImports(cssText, templateUrl);
var ret = null;
if (isPromise(inlinedCss)) {
DOM.setText(styleEl, '');
ret = (<Promise<string>>inlinedCss)
.then((css) => {
css = shimCssForComponent(css, hostComponentId);
DOM.setText(styleEl, css);
});
} else {
var css = shimCssForComponent(<string>inlinedCss, hostComponentId);
DOM.setText(styleEl, css);
}
constructor(styleHost) { super(styleHost); }
processStyleElement(hostComponentId: string, templateUrl: string, styleEl): void {
let cssText = DOM.getText(styleEl);
cssText = shimCssForComponent(cssText, hostComponentId);
DOM.setText(styleEl, cssText);
this._moveToStyleHost(styleEl);
return ret;
}
_moveToStyleHost(styleEl) {
_moveToStyleHost(styleEl): void {
DOM.remove(styleEl);
insertStyleElement(this.styleHost, styleEl);
}
processElement(hostComponentId: string, elementComponentId: string, element) {
processElement(hostComponentId: string, elementComponentId: string, element): void {
// Shim the element as a child of the compiled component
if (isPresent(hostComponentId)) {
var contentAttribute = getContentAttribute(getComponentId(hostComponentId));

View File

@ -1,14 +1,9 @@
import {isPromise} from 'angular2/src/facade/lang';
import {Promise} from 'angular2/src/facade/async';
import {DOM} from 'angular2/src/dom/dom_adapter';
import * as viewModule from '../view/view';
import {LightDom} from './light_dom';
import {ShadowDomStrategy} from './shadow_dom_strategy';
import {StyleUrlResolver} from './style_url_resolver';
import {StyleInliner} from 'angular2/src/render/dom/shadow_dom/style_inliner';
import {insertSharedStyleText} from './util';
/**
@ -21,10 +16,7 @@ import {insertSharedStyleText} from './util';
* - you can **not** use shadow DOM specific selectors in the styles
*/
export class EmulatedUnscopedShadowDomStrategy extends ShadowDomStrategy {
constructor(public styleInliner: StyleInliner, public styleUrlResolver: StyleUrlResolver,
public styleHost) {
super();
}
constructor(public styleHost) { super(); }
hasNativeContentElement(): boolean { return false; }
@ -34,21 +26,8 @@ export class EmulatedUnscopedShadowDomStrategy extends ShadowDomStrategy {
return new LightDom(lightDomView, el);
}
processStyleElement(hostComponentId: string, templateUrl: string, styleEl): Promise<any> {
processStyleElement(hostComponentId: string, templateUrl: string, styleEl): void {
var cssText = DOM.getText(styleEl);
cssText = this.styleUrlResolver.resolveUrls(cssText, templateUrl);
var inlinedCss = this.styleInliner.inlineImports(cssText, templateUrl);
var ret = null;
if (isPromise(inlinedCss)) {
DOM.setText(styleEl, '');
ret = (<Promise<string>>inlinedCss).then(css => { DOM.setText(styleEl, css); });
} else {
DOM.setText(styleEl, <string>inlinedCss);
}
insertSharedStyleText(cssText, this.styleHost, styleEl);
return ret;
}
}

View File

@ -1,12 +1,6 @@
import {isPromise} from 'angular2/src/facade/lang';
import {Promise} from 'angular2/src/facade/async';
import {Injectable} from 'angular2/di';
import {DOM} from 'angular2/src/dom/dom_adapter';
import {StyleUrlResolver} from './style_url_resolver';
import {ShadowDomStrategy} from './shadow_dom_strategy';
import {StyleInliner} from 'angular2/src/render/dom/shadow_dom/style_inliner';
/**
* This strategies uses the native Shadow DOM support.
@ -16,23 +10,5 @@ import {StyleInliner} from 'angular2/src/render/dom/shadow_dom/style_inliner';
*/
@Injectable()
export class NativeShadowDomStrategy extends ShadowDomStrategy {
constructor(public styleInliner: StyleInliner, public styleUrlResolver: StyleUrlResolver) {
super();
}
prepareShadowRoot(el) { return DOM.createShadowRoot(el); }
processStyleElement(hostComponentId: string, templateUrl: string, styleEl): Promise<any> {
var cssText = DOM.getText(styleEl);
cssText = this.styleUrlResolver.resolveUrls(cssText, templateUrl);
var inlinedCss = this.styleInliner.inlineImports(cssText, templateUrl);
if (isPromise(inlinedCss)) {
return (<Promise<string>>inlinedCss).then(css => { DOM.setText(styleEl, css); });
} else {
DOM.setText(styleEl, <string>inlinedCss);
return null;
}
}
}

View File

@ -11,7 +11,7 @@ import {
} from 'angular2/src/facade/lang';
/**
* This file is a port of shadowCSS from webcomponents.js to AtScript.
* This file is a port of shadowCSS from webcomponents.js to TypeScript.
*
* Please make sure to keep to edits in sync with the source file.
*

View File

@ -1,6 +1,4 @@
import {isBlank, isPresent, assertionsEnabled, isPromise} from 'angular2/src/facade/lang';
import {MapWrapper, List, ListWrapper} from 'angular2/src/facade/collection';
import {Promise, PromiseWrapper} from 'angular2/src/facade/async';
import {DOM} from 'angular2/src/dom/dom_adapter';
@ -11,8 +9,7 @@ import {ViewDefinition} from '../../api';
import {ShadowDomStrategy} from './shadow_dom_strategy';
export class ShadowDomCompileStep implements CompileStep {
constructor(public _shadowDomStrategy: ShadowDomStrategy, public _template: ViewDefinition,
public _subTaskPromises: List<Promise<any>>) {}
constructor(public _shadowDomStrategy: ShadowDomStrategy, public _view: ViewDefinition) {}
process(parent: CompileElement, current: CompileElement, control: CompileControl) {
var tagName = DOM.tagName(current.element).toUpperCase();
@ -22,17 +19,13 @@ export class ShadowDomCompileStep implements CompileStep {
this._processContentElement(current);
} else {
var componentId = current.isBound() ? current.inheritedElementBinder.componentId : null;
this._shadowDomStrategy.processElement(this._template.componentId, componentId,
current.element);
this._shadowDomStrategy.processElement(this._view.componentId, componentId, current.element);
}
}
_processStyleElement(current: CompileElement, control: CompileControl) {
var stylePromise = this._shadowDomStrategy.processStyleElement(
this._template.componentId, this._template.templateAbsUrl, current.element);
if (isPresent(stylePromise) && isPromise(stylePromise)) {
this._subTaskPromises.push(stylePromise);
}
this._shadowDomStrategy.processStyleElement(this._view.componentId, this._view.templateAbsUrl,
current.element);
// Style elements should not be further processed by the compiler, as they can not contain
// bindings. Skipping further compiler steps allow speeding up the compilation process.

View File

@ -1,28 +1,20 @@
import {isBlank, isPresent} from 'angular2/src/facade/lang';
import {Promise} from 'angular2/src/facade/async';
import * as viewModule from '../view/view';
import {LightDom} from './light_dom';
export class ShadowDomStrategy {
// Whether the strategy understands the native <content> tag
hasNativeContentElement(): boolean { return true; }
/**
* Prepares and returns the shadow root for the given element.
*/
// Prepares and returns the (emulated) shadow root for the given element.
prepareShadowRoot(el): any { return null; }
constructLightDom(lightDomView: viewModule.DomView, el): LightDom { return null; }
/**
* An optional step that can modify the template style elements.
*/
processStyleElement(hostComponentId: string, templateUrl: string, styleElement): Promise<any> {
return null;
}
// An optional step that can modify the template style elements.
processStyleElement(hostComponentId: string, templateUrl: string, styleElement): void {}
/**
* An optional step that can modify the template elements (style elements exlcuded).
*/
processElement(hostComponentId: string, elementComponentId: string, element) {}
// An optional step that can modify the template elements (style elements exlcuded).
processElement(hostComponentId: string, elementComponentId: string, element): void {}
}

View File

@ -23,8 +23,8 @@ import {XHR} from 'angular2/src/render/xhr';
import {ComponentUrlMapper} from 'angular2/src/core/compiler/component_url_mapper';
import {UrlResolver} from 'angular2/src/services/url_resolver';
import {AppRootUrl} from 'angular2/src/services/app_root_url';
import {StyleUrlResolver} from 'angular2/src/render/dom/shadow_dom/style_url_resolver';
import {StyleInliner} from 'angular2/src/render/dom/shadow_dom/style_inliner';
import {StyleUrlResolver} from 'angular2/src/render/dom/compiler/style_url_resolver';
import {StyleInliner} from 'angular2/src/render/dom/compiler/style_inliner';
import {NgZone} from 'angular2/src/core/zone/ng_zone';
import {DOM} from 'angular2/src/dom/dom_adapter';
@ -88,9 +88,7 @@ function _getAppBindings() {
bind(DOCUMENT_TOKEN)
.toValue(appDoc),
bind(ShadowDomStrategy)
.toFactory((styleInliner, styleUrlResolver, doc) => new EmulatedUnscopedShadowDomStrategy(
styleInliner, styleUrlResolver, doc.head),
[StyleInliner, StyleUrlResolver, DOCUMENT_TOKEN]),
.toFactory((doc) => new EmulatedUnscopedShadowDomStrategy(doc.head), [DOCUMENT_TOKEN]),
DomRenderer,
DefaultDomCompiler,
bind(Renderer).toAlias(DomRenderer),

View File

@ -1,6 +1,5 @@
library angular2.transform.template_compiler.compile_step_factory;
import 'dart:async';
import 'package:angular2/src/change_detection/parser/parser.dart' as ng;
import 'package:angular2/src/render/api.dart';
import 'package:angular2/src/render/dom/compiler/compile_step.dart';
@ -15,8 +14,7 @@ class CompileStepFactory implements base.CompileStepFactory {
final ng.Parser _parser;
CompileStepFactory(this._parser);
List<CompileStep> createSteps(
ViewDefinition template, List<Future> subTaskPromises) {
List<CompileStep> createSteps(ViewDefinition template) {
return [
new ViewSplitter(_parser),
new PropertyBindingParser(_parser),

View File

@ -7,6 +7,8 @@ import 'package:angular2/src/change_detection/parser/parser.dart' as ng;
import 'package:angular2/src/core/compiler/proto_view_factory.dart';
import 'package:angular2/src/render/api.dart';
import 'package:angular2/src/render/dom/compiler/compile_pipeline.dart';
import 'package:angular2/src/render/dom/compiler/style_inliner.dart';
import 'package:angular2/src/render/dom/compiler/style_url_resolver.dart';
import 'package:angular2/src/render/dom/compiler/template_loader.dart';
import 'package:angular2/src/render/xhr.dart' show XHR;
import 'package:angular2/src/reflection/reflection.dart';
@ -79,11 +81,17 @@ Future<String> processTemplates(AssetReader reader, AssetId entryPoint,
/// reflectively accessed from that template.
class _TemplateExtractor {
final CompileStepFactory _factory;
final TemplateLoader _loader;
TemplateLoader _loader;
_TemplateExtractor(XHR xhr)
: _factory = new CompileStepFactory(new ng.Parser(new ng.Lexer())),
_loader = new TemplateLoader(xhr, new UrlResolver());
: _factory = new CompileStepFactory(new ng.Parser(new ng.Lexer())) {
var urlResolver = new UrlResolver();
var styleUrlResolver = new StyleUrlResolver(urlResolver);
var styleInliner = new StyleInliner(xhr, styleUrlResolver, urlResolver);
_loader = new TemplateLoader(xhr, styleInliner, styleUrlResolver);
}
Future<_ExtractResult> extractTemplates(ViewDefinition viewDef) async {
// Check for "imperative views".
@ -98,9 +106,7 @@ class _TemplateExtractor {
var recordingCapabilities = new RecordingReflectionCapabilities();
reflector.reflectionCapabilities = recordingCapabilities;
var subtaskPromises = [];
var pipeline =
new CompilePipeline(_factory.createSteps(viewDef, subtaskPromises));
var pipeline = new CompilePipeline(_factory.createSteps(viewDef));
var compileElements =
pipeline.process(templateEl, ViewType.COMPONENT, viewDef.componentId);
@ -109,9 +115,7 @@ class _TemplateExtractor {
reflector.reflectionCapabilities = savedReflectionCapabilities;
return Future
.wait(subtaskPromises)
.then((_) => new _ExtractResult(recordingCapabilities, protoViewDto));
return new _ExtractResult(recordingCapabilities, protoViewDto);
}
}

View File

@ -62,8 +62,8 @@ export function main() {
protoViewFactoryResults: List<List<AppProtoView>>) {
var urlResolver = new FakeUrlResolver();
renderCompileRequests = [];
renderCompiler.spy('compile').andCallFake((template) => {
renderCompileRequests.push(template);
renderCompiler.spy('compile').andCallFake((view) => {
renderCompileRequests.push(view);
return PromiseWrapper.resolve(ListWrapper.removeAt(renderCompileResults, 0));
});
@ -467,12 +467,12 @@ export function main() {
});
}
function createDirectiveBinding(directiveResolver, type) {
function createDirectiveBinding(directiveResolver, type): DirectiveBinding {
var annotation = directiveResolver.resolve(type);
return DirectiveBinding.createFromType(type, annotation);
}
function createProtoView(elementBinders = null) {
function createProtoView(elementBinders = null): AppProtoView {
var pv = new AppProtoView(null, null, new Map(), null);
if (isBlank(elementBinders)) {
elementBinders = [];
@ -481,18 +481,19 @@ function createProtoView(elementBinders = null) {
return pv;
}
function createComponentElementBinder(directiveResolver, type) {
function createComponentElementBinder(directiveResolver, type): ElementBinder {
var binding = createDirectiveBinding(directiveResolver, type);
return new ElementBinder(0, null, 0, null, binding);
}
function createViewportElementBinder(nestedProtoView) {
function createViewportElementBinder(nestedProtoView): ElementBinder {
var elBinder = new ElementBinder(0, null, 0, null, null);
elBinder.nestedProtoView = nestedProtoView;
return elBinder;
}
function createRenderProtoView(elementBinders = null, type: renderApi.ViewType = null) {
function createRenderProtoView(elementBinders = null,
type: renderApi.ViewType = null): renderApi.ProtoViewDto {
if (isBlank(type)) {
type = renderApi.ViewType.COMPONENT;
}
@ -502,16 +503,16 @@ function createRenderProtoView(elementBinders = null, type: renderApi.ViewType =
return new renderApi.ProtoViewDto({elementBinders: elementBinders, type: type});
}
function createRenderComponentElementBinder(directiveIndex) {
function createRenderComponentElementBinder(directiveIndex): renderApi.ElementBinder {
return new renderApi.ElementBinder(
{directives: [new renderApi.DirectiveBinder({directiveIndex: directiveIndex})]});
}
function createRenderViewportElementBinder(nestedProtoView) {
function createRenderViewportElementBinder(nestedProtoView): renderApi.ElementBinder {
return new renderApi.ElementBinder({nestedProtoView: nestedProtoView});
}
function createRootProtoView(directiveResolver, type) {
function createRootProtoView(directiveResolver, type): AppProtoView {
return createProtoView([createComponentElementBinder(directiveResolver, type)]);
}
@ -577,23 +578,18 @@ class FakeAppRootUrl extends AppRootUrl {
class FakeTemplateResolver extends TemplateResolver {
_cmpTemplates: Map<Type, viewAnn.View>;
_cmpViews: Map<Type, viewAnn.View> = new Map();
constructor() {
super();
this._cmpTemplates = new Map();
}
constructor() { super(); }
resolve(component: Type): viewAnn.View {
var template = this._cmpTemplates.get(component);
if (isBlank(template)) {
// dynamic component
return null;
}
return template;
// returns null for dynamic components
return this._cmpViews.has(component) ? this._cmpViews.get(component) : null;
}
setView(component: Type, template: viewAnn.View) { this._cmpTemplates.set(component, template); }
setView(component: Type, template: viewAnn.View): void {
this._cmpViews.set(component, template);
}
}
class FakeProtoViewFactory extends ProtoViewFactory {

View File

@ -21,7 +21,7 @@ import {Component, View} from 'angular2/angular2';
import {NgIf} from 'angular2/src/directives/ng_if';
export function main() {
describe('if directive', () => {
describe('ng-if directive', () => {
it('should work in a template attribute',
inject([TestBed, AsyncTestCompleter], (tb: TestBed, async) => {
var html = '<div><copy-me template="ng-if booleanCondition">hello</copy-me></div>';

View File

@ -24,8 +24,6 @@ import {CompileStepFactory} from 'angular2/src/render/dom/compiler/compile_step_
import {CompileControl} from 'angular2/src/render/dom/compiler/compile_control';
import {TemplateLoader} from 'angular2/src/render/dom/compiler/template_loader';
import {UrlResolver} from 'angular2/src/services/url_resolver';
import {resolveInternalDomProtoView} from 'angular2/src/render/dom/view/proto_view';
export function runCompilerCommonTests() {
@ -111,30 +109,6 @@ export function runCompilerCommonTests() {
});
}));
it('should wait for async subtasks to be resolved', inject([AsyncTestCompleter], (async) => {
var subTasksCompleted = false;
var completer = PromiseWrapper.completer();
var compiler = createCompiler((parent, current, control) => {
mockStepFactory.subTaskPromises.push(
completer.promise.then((_) => { subTasksCompleted = true; }));
});
// It should always return a Promise because the subtask is async
var pvPromise = compiler.compile(
new ViewDefinition({componentId: 'someId', template: 'some component'}));
expect(pvPromise).toBePromise();
expect(subTasksCompleted).toEqual(false);
// The Promise should resolve after the subtask is ready
completer.resolve(null);
pvPromise.then((protoView) => {
expect(subTasksCompleted).toEqual(true);
async.done();
});
}));
it('should return ProtoViews of type COMPONENT_VIEW_TYPE',
inject([AsyncTestCompleter], (async) => {
var compiler = createCompiler(EMPTY_STEP);
@ -174,10 +148,8 @@ class MockStepFactory extends CompileStepFactory {
super();
this.steps = steps;
}
createSteps(viewDef, subTaskPromises) {
createSteps(viewDef): List<CompileStep> {
this.viewDef = viewDef;
this.subTaskPromises = subTaskPromises;
ListWrapper.forEach(this.subTaskPromises, (p) => this.subTaskPromises.push(p));
return this.steps;
}
}
@ -199,20 +171,20 @@ var EMPTY_STEP = (parent, current, control) => {
class FakeTemplateLoader extends TemplateLoader {
_urlData: Map<string, string>;
constructor(urlData) {
super(null, new UrlResolver());
super(null, null, null);
this._urlData = urlData;
}
load(template: ViewDefinition) {
if (isPresent(template.template)) {
return PromiseWrapper.resolve(DOM.createTemplate(template.template));
load(view: ViewDefinition): Promise<any> {
if (isPresent(view.template)) {
return PromiseWrapper.resolve(DOM.createTemplate(view.template));
}
if (isPresent(template.templateAbsUrl)) {
var content = this._urlData.get(template.templateAbsUrl);
if (isPresent(view.templateAbsUrl)) {
var content = this._urlData.get(view.templateAbsUrl);
return isPresent(content) ?
PromiseWrapper.resolve(DOM.createTemplate(content)) :
PromiseWrapper.reject(`Failed to fetch url "${template.templateAbsUrl}"`, null);
PromiseWrapper.reject(`Failed to fetch url "${view.templateAbsUrl}"`, null);
}
throw new BaseException('View should have either the templateUrl or template property set');

View File

@ -11,7 +11,7 @@ import {
it,
xit,
} from 'angular2/test_lib';
import {StyleInliner} from 'angular2/src/render/dom/shadow_dom/style_inliner';
import {StyleInliner} from 'angular2/src/render/dom/compiler/style_inliner';
import {isBlank} from 'angular2/src/facade/lang';
import {Promise, PromiseWrapper} from 'angular2/src/facade/async';

View File

@ -1,5 +1,5 @@
import {describe, it, expect, beforeEach, ddescribe, iit, xit, el} from 'angular2/test_lib';
import {StyleUrlResolver} from 'angular2/src/render/dom/shadow_dom/style_url_resolver';
import {StyleUrlResolver} from 'angular2/src/render/dom/compiler/style_url_resolver';
import {UrlResolver} from 'angular2/src/services/url_resolver';

View File

@ -12,19 +12,27 @@ import {
} from 'angular2/test_lib';
import {DOM} from 'angular2/src/dom/dom_adapter';
import {TemplateLoader} from 'angular2/src/render/dom/compiler/template_loader';
import {StyleInliner} from 'angular2/src/render/dom/compiler/style_inliner';
import {StyleUrlResolver} from 'angular2/src/render/dom/compiler/style_url_resolver';
import {UrlResolver} from 'angular2/src/services/url_resolver';
import {ViewDefinition} from 'angular2/src/render/api';
import {PromiseWrapper} from 'angular2/src/facade/async';
import {PromiseWrapper, Promise} from 'angular2/src/facade/async';
import {StringWrapper, isBlank, isPresent} from 'angular2/src/facade/lang';
import {MapWrapper, ListWrapper} from 'angular2/src/facade/collection';
import {XHR} from 'angular2/src/render/xhr';
import {MockXHR} from 'angular2/src/render/xhr_mock';
export function main() {
describe('TemplateLoader', () => {
var loader, xhr;
var loader, xhr, styleUrlResolver, urlResolver;
beforeEach(() => {
xhr = new MockXHR();
loader = new TemplateLoader(xhr, new FakeUrlResolver());
urlResolver = new FakeUrlResolver();
styleUrlResolver = new StyleUrlResolver(urlResolver);
let styleInliner = new StyleInliner(xhr, styleUrlResolver, urlResolver);
loader = new TemplateLoader(xhr, styleInliner, styleUrlResolver);
});
describe('html', () => {
@ -46,6 +54,33 @@ export function main() {
xhr.flush();
}));
it('should resolve urls in styles', inject([AsyncTestCompleter], (async) => {
xhr.expect('base/foo.html',
'<style>.foo { background-image: url("double.jpg"); }</style>');
var template = new ViewDefinition({templateAbsUrl: 'base/foo.html'});
loader.load(template).then((el) => {
expect(DOM.content(el))
.toHaveText(".foo { background-image: url('/base/double.jpg'); }");
async.done();
});
xhr.flush();
}));
it('should inline styles', inject([AsyncTestCompleter], (async) => {
let xhr = new FakeXHR();
xhr.reply('base/foo.html', '<style>@import "foo.css";</style>');
xhr.reply('/base/foo.css', '/* foo.css */');
let styleInliner = new StyleInliner(xhr, styleUrlResolver, urlResolver);
let loader = new TemplateLoader(xhr, styleInliner, styleUrlResolver);
var template = new ViewDefinition({templateAbsUrl: 'base/foo.html'});
loader.load(template).then((el) => {
expect(DOM.getInnerHTML(el)).toEqual("<style>/* foo.css */\n</style>");
async.done();
});
}));
it('should return a new template element on each call',
inject([AsyncTestCompleter], (async) => {
var firstEl;
@ -91,8 +126,17 @@ export function main() {
var template = new ViewDefinition({template: 'html', styles: ['style 1', 'style 2']});
loader.load(template).then((el) => {
expect(DOM.getInnerHTML(el))
.toEqual(
'<style type="text/css">style 1</style><style type="text/css">style 2</style>html');
.toEqual('<style>style 1</style><style>style 2</style>html');
async.done();
});
}));
it('should resolve urls in inline styles', inject([AsyncTestCompleter], (async) => {
var template = new ViewDefinition(
{template: 'html', styles: ['.foo { background-image: url("double.jpg"); }']});
loader.load(template).then((el) => {
expect(DOM.getInnerHTML(el))
.toEqual("<style>.foo { background-image: url('/double.jpg'); }</style>html");
async.done();
});
}));
@ -108,13 +152,29 @@ export function main() {
});
loader.load(template).then((el) => {
expect(DOM.getInnerHTML(el))
.toEqual(
'<style type="text/css">i1</style><style type="text/css">1</style><style type="text/css">2</style>xhr template');
.toEqual('<style>i1</style><style>1</style><style>2</style>xhr template');
async.done();
});
xhr.flush();
}));
it('should inline styles', inject([AsyncTestCompleter], (async) => {
let xhr = new FakeXHR();
xhr.reply('base/foo.html', '<p>template</p>');
xhr.reply('/base/foo.css', '/* foo.css */');
let styleInliner = new StyleInliner(xhr, styleUrlResolver, urlResolver);
let loader = new TemplateLoader(xhr, styleInliner, styleUrlResolver);
var template = new ViewDefinition(
{templateAbsUrl: 'base/foo.html', styles: ['@import "foo.css";']});
loader.load(template).then((el) => {
expect(DOM.getInnerHTML(el)).toEqual("<style>/* foo.css */\n</style><p>template</p>");
async.done();
});
}));
it('should return a rejected Promise when XHR loading fails',
inject([AsyncTestCompleter], (async) => {
xhr.expect('base/foo.css', null);
@ -136,5 +196,27 @@ class SomeComponent {}
class FakeUrlResolver extends UrlResolver {
constructor() { super(); }
resolve(baseUrl: string, url: string): string { return baseUrl + url; }
resolve(baseUrl: string, url: string): string {
if (url.length > 0 && url[0] == '/') return url;
if (!isPresent(baseUrl)) return `/${url}`;
var parts: List<string> = baseUrl.split('/');
if (parts.length > 1) {
ListWrapper.removeLast(parts);
}
parts.push(url);
return '/' + parts.join('/');
}
}
class FakeXHR extends XHR {
_responses: Map<string, string> = new Map();
constructor() { super(); }
get(url: string): Promise<string> {
return this._responses.has(url) ? PromiseWrapper.resolve(this._responses.get(url)) :
PromiseWrapper.reject('xhr error', null);
}
reply(url: string, response: string): void { this._responses.set(url, response); }
}

View File

@ -13,12 +13,7 @@ import {
normalizeCSS
} from 'angular2/test_lib';
import {isPresent, isBlank} from 'angular2/src/facade/lang';
import {DOM} from 'angular2/src/dom/dom_adapter';
import {Map, MapWrapper} from 'angular2/src/facade/collection';
import {PromiseWrapper, Promise} from 'angular2/src/facade/async';
import {XHR} from 'angular2/src/render/xhr';
import {
EmulatedScopedShadowDomStrategy,
@ -26,21 +21,14 @@ import {
import {
resetShadowDomCache,
} from 'angular2/src/render/dom/shadow_dom/util';
import {UrlResolver} from 'angular2/src/services/url_resolver';
import {StyleUrlResolver} from 'angular2/src/render/dom/shadow_dom/style_url_resolver';
import {StyleInliner} from 'angular2/src/render/dom/shadow_dom/style_inliner';
export function main() {
describe('EmulatedScopedShadowDomStrategy', () => {
var xhr, styleHost, strategy;
var styleHost, strategy;
beforeEach(() => {
var urlResolver = new UrlResolver();
var styleUrlResolver = new StyleUrlResolver(urlResolver);
xhr = new FakeXHR();
var styleInliner = new StyleInliner(xhr, styleUrlResolver, urlResolver);
styleHost = el('<div></div>');
strategy = new EmulatedScopedShadowDomStrategy(styleInliner, styleUrlResolver, styleHost);
strategy = new EmulatedScopedShadowDomStrategy(styleHost);
resetShadowDomCache();
});
@ -49,34 +37,12 @@ export function main() {
expect(strategy.prepareShadowRoot(host)).toBe(host);
});
it('should rewrite style urls', () => {
var styleElement = el('<style>.foo {background-image: url("img.jpg");}</style>');
strategy.processStyleElement('someComponent', 'http://base', styleElement);
expect(normalizeCSS(DOM.getText(styleElement)))
.toEqual(".foo[_ngcontent-0] { background-image:url(http://base/img.jpg); }");
});
it('should scope styles', () => {
var styleElement = el('<style>.foo {} :host {}</style>');
strategy.processStyleElement('someComponent', 'http://base', styleElement);
expect(styleElement).toHaveText(".foo[_ngcontent-0] {\n\n}\n\n[_nghost-0] {\n\n}");
});
it('should inline @import rules', inject([AsyncTestCompleter], (async) => {
xhr.reply('http://base/one.css', '.one {}');
var styleElement = el('<style>@import "one.css";</style>');
var stylePromise =
strategy.processStyleElement('someComponent', 'http://base', styleElement);
expect(stylePromise).toBePromise();
expect(styleElement).toHaveText('');
stylePromise.then((_) => {
expect(styleElement).toHaveText('.one[_ngcontent-0] {\n\n}');
async.done();
});
}));
it('should return the same style given the same component', () => {
var styleElement = el('<style>.foo {} :host {}</style>');
strategy.processStyleElement('someComponent', 'http://base', styleElement);
@ -97,22 +63,6 @@ export function main() {
expect(DOM.getText(styleElement)).not.toEqual(DOM.getText(styleElement2));
});
it('should move the style element to the style host when @imports are present',
inject([AsyncTestCompleter], (async) => {
xhr.reply('http://base/one.css', '.one {}');
var compileElement = el('<div><style>@import "one.css";</style></div>');
var styleElement = DOM.firstChild(compileElement);
var stylePromise =
strategy.processStyleElement('someComponent', 'http://base', styleElement);
stylePromise.then((_) => {
expect(compileElement).toHaveText('');
expect(styleHost).toHaveText('.one[_ngcontent-0] {\n\n}');
async.done();
});
}));
it('should move the style element to the style host', () => {
var compileElement = el('<div><style>.one {}</style></div>');
var styleElement = DOM.firstChild(compileElement);
@ -136,23 +86,3 @@ export function main() {
});
}
class FakeXHR extends XHR {
_responses: Map<string, string>;
constructor() {
super();
this._responses = new Map();
}
get(url: string): Promise<string> {
var response = this._responses.get(url);
if (isBlank(response)) {
return PromiseWrapper.reject('xhr error', null);
}
return PromiseWrapper.resolve(response);
}
reply(url: string, response: string) { this._responses.set(url, response); }
}

View File

@ -13,7 +13,7 @@ import {
} from 'angular2/test_lib';
import {DOM} from 'angular2/src/dom/dom_adapter';
import {Map, ListWrapper} from 'angular2/src/facade/collection';
import {ListWrapper} from 'angular2/src/facade/collection';
import {
EmulatedUnscopedShadowDomStrategy,
@ -21,28 +21,16 @@ import {
import {
resetShadowDomCache,
} from 'angular2/src/render/dom/shadow_dom/util';
import {UrlResolver} from 'angular2/src/services/url_resolver';
import {StyleUrlResolver} from 'angular2/src/render/dom/shadow_dom/style_url_resolver';
import {StyleInliner} from 'angular2/src/render/dom/shadow_dom/style_inliner';
import {isBlank} from 'angular2/src/facade/lang';
import {PromiseWrapper, Promise} from 'angular2/src/facade/async';
import {XHR} from 'angular2/src/render/xhr';
export function main() {
var strategy;
describe('EmulatedUnscopedShadowDomStrategy', () => {
var xhr, styleHost;
var styleHost;
beforeEach(() => {
var urlResolver = new UrlResolver();
var styleUrlResolver = new StyleUrlResolver(urlResolver);
xhr = new FakeXHR();
var styleInliner = new StyleInliner(xhr, styleUrlResolver, urlResolver);
styleHost = el('<div></div>');
strategy = new EmulatedUnscopedShadowDomStrategy(styleInliner, styleUrlResolver, styleHost);
strategy = new EmulatedUnscopedShadowDomStrategy(styleHost);
resetShadowDomCache();
});
@ -51,27 +39,6 @@ export function main() {
expect(strategy.prepareShadowRoot(host)).toBe(host);
});
it('should rewrite style urls', () => {
var styleElement = el('<style>.foo {background-image: url("img.jpg");}</style>');
strategy.processStyleElement('someComponent', 'http://base', styleElement);
expect(styleElement).toHaveText(".foo {background-image: url('http://base/img.jpg');}");
});
it('should inline @import rules', inject([AsyncTestCompleter], (async) => {
xhr.reply('http://base/one.css', '.one {}');
var styleElement = el('<style>@import "one.css";</style>');
var stylePromise =
strategy.processStyleElement('someComponent', 'http://base', styleElement);
expect(stylePromise).toBePromise();
expect(styleElement).toHaveText('');
stylePromise.then((_) => {
expect(styleElement).toHaveText('.one {}\n');
async.done();
});
}));
it('should move the style element to the style host', () => {
var compileElement = el('<div><style>.one {}</style></div>');
var styleElement = DOM.firstChild(compileElement);
@ -96,23 +63,3 @@ export function main() {
});
}
class FakeXHR extends XHR {
_responses: Map<string, string>;
constructor() {
super();
this._responses = <Map<string, string>>{};
}
get(url: string): Promise<string> {
var response = this._responses[url];
if (isBlank(response)) {
return PromiseWrapper.reject('xhr error', null);
}
return PromiseWrapper.resolve(response);
}
reply(url: string, response: string) { this._responses[url] = response; }
}

View File

@ -15,15 +15,6 @@ import {
import {
NativeShadowDomStrategy
} from 'angular2/src/render/dom/shadow_dom/native_shadow_dom_strategy';
import {UrlResolver} from 'angular2/src/services/url_resolver';
import {StyleUrlResolver} from 'angular2/src/render/dom/shadow_dom/style_url_resolver';
import {StyleInliner} from 'angular2/src/render/dom/shadow_dom/style_inliner';
import {XHR} from 'angular2/src/render/xhr';
import {isBlank} from 'angular2/src/facade/lang';
import {PromiseWrapper, Promise} from 'angular2/src/facade/async';
import {Map} from 'angular2/src/facade/collection';
import {DOM} from 'angular2/src/dom/dom_adapter';
@ -31,14 +22,7 @@ export function main() {
var strategy;
describe('NativeShadowDomStrategy', () => {
var xhr;
beforeEach(() => {
var urlResolver = new UrlResolver();
var styleUrlResolver = new StyleUrlResolver(urlResolver);
xhr = new FakeXHR();
var styleInliner = new StyleInliner(xhr, styleUrlResolver, urlResolver);
strategy = new NativeShadowDomStrategy(styleInliner, styleUrlResolver);
});
beforeEach(() => { strategy = new NativeShadowDomStrategy(); });
if (DOM.supportsNativeShadowDOM()) {
it('should use the native shadow root', () => {
@ -46,47 +30,5 @@ export function main() {
expect(strategy.prepareShadowRoot(host)).toBe(DOM.getShadowRoot(host));
});
}
it('should rewrite style urls', () => {
var styleElement = el('<style>.foo {background-image: url("img.jpg");}</style>');
strategy.processStyleElement('someComponent', 'http://base', styleElement);
expect(styleElement)
.toHaveText(".foo {" + "background-image: url('http://base/img.jpg');" + "}");
});
it('should inline @import rules', inject([AsyncTestCompleter], (async) => {
xhr.reply('http://base/one.css', '.one {}');
var styleElement = el('<style>@import "one.css";</style>');
var stylePromise =
strategy.processStyleElement('someComponent', 'http://base', styleElement);
expect(stylePromise).toBePromise();
stylePromise.then((_) => {
expect(styleElement).toHaveText('.one {}\n');
async.done();
});
}));
});
}
class FakeXHR extends XHR {
_responses: Map<string, string>;
constructor() {
super();
this._responses = <Map<string, string>>{};
}
get(url: string): Promise<string> {
var response = this._responses[url];
if (isBlank(response)) {
return PromiseWrapper.reject('xhr error', null);
}
return PromiseWrapper.resolve(response);
}
reply(url: string, response: string) { this._responses[url] = response; }
}

View File

@ -29,35 +29,21 @@ import {
import {
NativeShadowDomStrategy
} from 'angular2/src/render/dom/shadow_dom/native_shadow_dom_strategy';
import {StyleUrlResolver} from 'angular2/src/render/dom/shadow_dom/style_url_resolver';
import {StyleInliner} from 'angular2/src/render/dom/shadow_dom/style_inliner';
import {DomTestbed, elRef} from './dom_testbed';
export function main() {
describe('ShadowDom integration tests', function() {
var styleHost;
var styleHost = DOM.createElement('div');
var strategies = {
"scoped":
bind(ShadowDomStrategy)
.toFactory((styleInliner, styleUrlResolver) => new EmulatedScopedShadowDomStrategy(
styleInliner, styleUrlResolver, styleHost),
[StyleInliner, StyleUrlResolver]),
"unscoped":
bind(ShadowDomStrategy)
.toFactory((styleInliner, styleUrlResolver) => new EmulatedUnscopedShadowDomStrategy(
styleInliner, styleUrlResolver, null),
[StyleInliner, StyleUrlResolver])
"scoped": bind(ShadowDomStrategy).toValue(new EmulatedScopedShadowDomStrategy(styleHost)),
"unscoped": bind(ShadowDomStrategy).toValue(new EmulatedUnscopedShadowDomStrategy(styleHost))
};
if (DOM.supportsNativeShadowDOM()) {
StringMapWrapper.set(
strategies, "native",
bind(ShadowDomStrategy)
.toFactory((styleInliner, styleUrlResolver) =>
new NativeShadowDomStrategy(styleInliner, styleUrlResolver),
[StyleInliner, StyleUrlResolver]));
StringMapWrapper.set(strategies, "native",
bind(ShadowDomStrategy).toValue(new NativeShadowDomStrategy()));
}
beforeEach(() => { styleHost = el('<div></div>'); });
StringMapWrapper.forEach(strategies, (strategyBinding, name) => {
describe(`${name} shadow dom strategy`, () => {

View File

@ -16,10 +16,7 @@ import {Component, Directive, View} from 'angular2/angular2';
import {TemplateLoader} from 'angular2/src/render/dom/compiler/template_loader';
import {TemplateResolver} from 'angular2/src/core/compiler/template_resolver';
import {UrlResolver} from 'angular2/src/services/url_resolver';
import {StyleUrlResolver} from 'angular2/src/render/dom/shadow_dom/style_url_resolver';
import {StyleInliner} from 'angular2/src/render/dom/shadow_dom/style_inliner';
import {AppRootUrl} from 'angular2/src/services/app_root_url';
import {ComponentUrlMapper} from 'angular2/src/core/compiler/component_url_mapper';
import {reflector} from 'angular2/src/reflection/reflection';
@ -39,11 +36,9 @@ export function main() {
var templateResolver = new MultipleTemplateResolver(
count, [BenchmarkComponentNoBindings, BenchmarkComponentWithBindings]);
var urlResolver = new UrlResolver();
var styleUrlResolver = new StyleUrlResolver(urlResolver);
var styleInliner = new StyleInliner(null, styleUrlResolver, urlResolver);
var shadowDomStrategy = new NativeShadowDomStrategy(styleInliner, styleUrlResolver);
var shadowDomStrategy = new NativeShadowDomStrategy();
var renderCompiler = new rc.DefaultDomCompiler(new Parser(new Lexer()), shadowDomStrategy,
new TemplateLoader(null, urlResolver));
new TemplateLoader(null, null, null));
var compiler = new Compiler(
reader, cache, templateResolver, new ComponentUrlMapper(), urlResolver, renderCompiler,
new ProtoViewFactory(new DynamicChangeDetection(null)), new FakeAppRootUrl());

View File

@ -27,16 +27,16 @@ export class DemoUrlResolver extends UrlResolver {
constructor() {
super();
if (isBlank(UrlResolver.a)) {
UrlResolver.a = DOM.createElement('a');
if (isBlank(DemoUrlResolver.a)) {
DemoUrlResolver.a = DOM.createElement('a');
}
this.isInPubServe = _isInPubServe();
}
resolve(baseUrl: string, url: string): string {
if (isBlank(baseUrl)) {
DOM.resolveAndSetHref(UrlResolver.a, url, null);
return DOM.getHref(UrlResolver.a);
DOM.resolveAndSetHref(DemoUrlResolver.a, url, null);
return DOM.getHref(DemoUrlResolver.a);
}
if (isBlank(url) || url == '') {