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
@@ -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 {
@@ -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>';
@@ -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');
@@ -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';
@@ -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';
@@ -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); }
}
@@ -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); }
}
@@ -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; }
}
@@ -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; }
}
@@ -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`, () => {