diff --git a/modules/angular2/src/dom/browser_adapter.dart b/modules/angular2/src/dom/browser_adapter.dart index 37b9e5c6b3..b9528b266c 100644 --- a/modules/angular2/src/dom/browser_adapter.dart +++ b/modules/angular2/src/dom/browser_adapter.dart @@ -238,6 +238,9 @@ class BrowserDomAdapter extends GenericBrowserDomAdapter { void setChecked(InputElement el, bool isChecked) { el.checked = isChecked; } + Comment createComment(String text) { + return new Comment(text); + } TemplateElement createTemplate(String html) { var t = new TemplateElement(); // We do not sanitize because templates are part of the application code @@ -341,6 +344,9 @@ class BrowserDomAdapter extends GenericBrowserDomAdapter { Node importIntoDoc(Node node) { return document.importNode(node, true); } + Node adoptNode(Node node) { + return document.adoptNode(node); + } bool isPageRule(CssRule rule) => rule is CssPageRule; bool isStyleRule(CssRule rule) => rule is CssStyleRule; bool isMediaRule(CssRule rule) => rule is CssMediaRule; diff --git a/modules/angular2/src/dom/browser_adapter.ts b/modules/angular2/src/dom/browser_adapter.ts index db285457cf..a20a64f081 100644 --- a/modules/angular2/src/dom/browser_adapter.ts +++ b/modules/angular2/src/dom/browser_adapter.ts @@ -153,6 +153,7 @@ export class BrowserDomAdapter extends GenericBrowserDomAdapter { setValue(el, value: string) { el.value = value; } getChecked(el): boolean { return el.checked; } setChecked(el, value: boolean) { el.checked = value; } + createComment(text: string): Comment { return document.createComment(text); } createTemplate(html): HTMLElement { var t = document.createElement('template'); t.innerHTML = html; @@ -238,6 +239,7 @@ export class BrowserDomAdapter extends GenericBrowserDomAdapter { } return document.importNode(toImport, true); } + adoptNode(node: Node): any { return document.adoptNode(node); } isPageRule(rule): boolean { return rule.type === CSSRule.PAGE_RULE; } isStyleRule(rule): boolean { return rule.type === CSSRule.STYLE_RULE; } isMediaRule(rule): boolean { return rule.type === CSSRule.MEDIA_RULE; } diff --git a/modules/angular2/src/dom/dom_adapter.ts b/modules/angular2/src/dom/dom_adapter.ts index 3bba4d92ce..8136aa229b 100644 --- a/modules/angular2/src/dom/dom_adapter.ts +++ b/modules/angular2/src/dom/dom_adapter.ts @@ -69,6 +69,7 @@ export class DomAdapter { setValue(el, value: string) { throw _abstract(); } getChecked(el): boolean { throw _abstract(); } setChecked(el, value: boolean) { throw _abstract(); } + createComment(text: string): any { throw _abstract(); } createTemplate(html): HTMLElement { throw _abstract(); } createElement(tagName, doc = null): HTMLElement { throw _abstract(); } createTextNode(text: string, doc = null): Text { throw _abstract(); } @@ -110,6 +111,7 @@ export class DomAdapter { hasShadowRoot(node): boolean { throw _abstract(); } isShadowRoot(node): boolean { throw _abstract(); } importIntoDoc /**/ (node: Node /*T*/): Node /*T*/ { throw _abstract(); } + adoptNode /**/ (node: Node /*T*/): Node /*T*/ { throw _abstract(); } isPageRule(rule): boolean { throw _abstract(); } isStyleRule(rule): boolean { throw _abstract(); } isMediaRule(rule): boolean { throw _abstract(); } diff --git a/modules/angular2/src/dom/html_adapter.dart b/modules/angular2/src/dom/html_adapter.dart index b304de3ba3..b7656393b3 100644 --- a/modules/angular2/src/dom/html_adapter.dart +++ b/modules/angular2/src/dom/html_adapter.dart @@ -184,6 +184,7 @@ class Html5LibDomAdapter implements DomAdapter { setChecked(el, bool value) { throw 'not implemented'; } + createComment(String text) => new Comment(text); createTemplate(String html) => createElement('template')..innerHtml = html; createElement(tagName, [doc]) { return new Element.tag(tagName); @@ -292,6 +293,9 @@ class Html5LibDomAdapter implements DomAdapter { importIntoDoc(node) { throw 'not implemented'; } + adoptNode(node) { + throw 'not implemented'; + } bool isPageRule(rule) { throw 'not implemented'; } diff --git a/modules/angular2/src/dom/parse5_adapter.ts b/modules/angular2/src/dom/parse5_adapter.ts index 4acfee7cc6..daa7a9c54e 100644 --- a/modules/angular2/src/dom/parse5_adapter.ts +++ b/modules/angular2/src/dom/parse5_adapter.ts @@ -77,6 +77,9 @@ export class Parse5DomAdapter extends DomAdapter { return res; } elementMatches(node, selector: string, matcher = null): boolean { + if (!selector || selector === '*') { + return true; + } var result = false; if (selector && selector.charAt(0) == "#") { result = this.getAttribute(node, 'id') == selector.substring(1); @@ -252,6 +255,7 @@ export class Parse5DomAdapter extends DomAdapter { setValue(el, value: string) { el.value = value; } getChecked(el): boolean { return el.checked; } setChecked(el, value: boolean) { el.checked = value; } + createComment(text: string): Comment { return treeAdapter.createCommentNode(text); } createTemplate(html): HTMLElement { var template = treeAdapter.createElement("template", 'http://www.w3.org/1999/xhtml', []); var content = parser.parseFragment(html); @@ -447,6 +451,7 @@ export class Parse5DomAdapter extends DomAdapter { hasShadowRoot(node): boolean { return isPresent(node.shadowRoot); } isShadowRoot(node): boolean { return this.getShadowRoot(node) == node; } importIntoDoc(node): any { return this.clone(node); } + adoptNode(node): any { return node; } isPageRule(rule): boolean { return rule.type === 6; // CSSRule.PAGE_RULE } diff --git a/modules/angular2/src/render/dom/util.ts b/modules/angular2/src/render/dom/util.ts index a208efa355..ce646ad2e8 100644 --- a/modules/angular2/src/render/dom/util.ts +++ b/modules/angular2/src/render/dom/util.ts @@ -12,6 +12,8 @@ export const EVENT_TARGET_SEPARATOR = ':'; export const NG_CONTENT_ELEMENT_NAME = 'ng-content'; export const NG_SHADOW_ROOT_ELEMENT_NAME = 'shadow-root'; +const MAX_IN_MEMORY_ELEMENTS_PER_TEMPLATE = 20; + var CAMEL_CASE_REGEXP = /([A-Z])/g; var DASH_CASE_REGEXP = /-([a-z])/g; @@ -57,8 +59,7 @@ export class ClonedProtoView { export function cloneAndQueryProtoView(pv: DomProtoView, importIntoDocument: boolean): ClonedProtoView { - var templateContent = importIntoDocument ? DOM.importIntoDoc(DOM.content(pv.rootElement)) : - DOM.clone(DOM.content(pv.rootElement)); + var templateContent = pv.cloneableTemplate.clone(importIntoDocument); var boundElements = queryBoundElements(templateContent, pv.isSingleElementFragment); var boundTextNodes = queryBoundTextNodes(templateContent, pv.rootTextNodeIndices, boundElements, @@ -140,3 +141,45 @@ export function prependAll(parentNode: Node, nodes: Node[]) { lastInsertedNode = node; }); } + +export interface CloneableTemplate { clone(importIntoDoc: boolean): Node; } + +export class SerializedCloneableTemplate implements CloneableTemplate { + templateString: string; + constructor(templateRoot: Element) { this.templateString = DOM.getInnerHTML(templateRoot); } + clone(importIntoDoc: boolean): Node { + var result = DOM.content(DOM.createTemplate(this.templateString)); + if (importIntoDoc) { + result = DOM.adoptNode(result); + } + return result; + } +} + +export class ReferenceCloneableTemplate implements CloneableTemplate { + constructor(public templateRoot: Element) {} + clone(importIntoDoc: boolean): Node { + if (importIntoDoc) { + return DOM.importIntoDoc(DOM.content(this.templateRoot)); + } else { + return DOM.clone(DOM.content(this.templateRoot)); + } + } +} + +export function prepareTemplateForClone(templateRoot: Element): CloneableTemplate { + var root = DOM.content(templateRoot); + var elementCount = DOM.querySelectorAll(root, '*').length; + var firstChild = DOM.firstChild(root); + var forceSerialize = + isPresent(firstChild) && DOM.isCommentNode(firstChild) ? DOM.nodeValue(firstChild) : null; + if (forceSerialize == 'nocache') { + return new SerializedCloneableTemplate(templateRoot); + } else if (forceSerialize == 'cache') { + return new ReferenceCloneableTemplate(templateRoot); + } else if (elementCount > MAX_IN_MEMORY_ELEMENTS_PER_TEMPLATE) { + return new SerializedCloneableTemplate(templateRoot); + } else { + return new ReferenceCloneableTemplate(templateRoot); + } +} \ No newline at end of file diff --git a/modules/angular2/src/render/dom/view/proto_view.ts b/modules/angular2/src/render/dom/view/proto_view.ts index 9998b31df3..5ac3c7a99a 100644 --- a/modules/angular2/src/render/dom/view/proto_view.ts +++ b/modules/angular2/src/render/dom/view/proto_view.ts @@ -5,6 +5,8 @@ import {RenderProtoViewRef, ViewType, ViewEncapsulation} from '../../api'; import {DOM} from 'angular2/src/dom/dom_adapter'; +import {prepareTemplateForClone, CloneableTemplate} from '../util'; + export function resolveInternalDomProtoView(protoViewRef: RenderProtoViewRef): DomProtoView { return (protoViewRef)._protoView; } @@ -25,12 +27,12 @@ export class DomProtoView { var isSingleElementFragment = fragmentsRootNodeCount.length === 1 && fragmentsRootNodeCount[0] === 1 && DOM.isElementNode(DOM.firstChild(DOM.content(rootElement))); - return new DomProtoView(type, rootElement, viewEncapsulation, elementBinders, hostAttributes, - rootTextNodeIndices, boundTextNodeCount, fragmentsRootNodeCount, - isSingleElementFragment); + return new DomProtoView(type, prepareTemplateForClone(rootElement), viewEncapsulation, + elementBinders, hostAttributes, rootTextNodeIndices, boundTextNodeCount, + fragmentsRootNodeCount, isSingleElementFragment); } - constructor(public type: ViewType, public rootElement: Element, + constructor(public type: ViewType, public cloneableTemplate: CloneableTemplate, public encapsulation: ViewEncapsulation, public elementBinders: List, public hostAttributes: Map, public rootTextNodeIndices: number[], diff --git a/modules/angular2/src/render/dom/view/proto_view_merger.ts b/modules/angular2/src/render/dom/view/proto_view_merger.ts index 4d9cef3760..6a213c9ab2 100644 --- a/modules/angular2/src/render/dom/view/proto_view_merger.ts +++ b/modules/angular2/src/render/dom/view/proto_view_merger.ts @@ -251,6 +251,7 @@ function appendComponentNodesToHost(hostProtoView: ClonedProtoView, binderIdx: n function projectMatchingNodes(selector: string, contentElement: Element, nodes: Node[]): Node[] { var remaining = []; + DOM.insertBefore(contentElement, DOM.createComment('[')); for (var i = 0; i < nodes.length; i++) { var node = nodes[i]; var matches = false; @@ -265,6 +266,7 @@ function projectMatchingNodes(selector: string, contentElement: Element, nodes: remaining.push(node); } } + DOM.insertBefore(contentElement, DOM.createComment(']')); DOM.remove(contentElement); return remaining; } diff --git a/modules/angular2/src/test_lib/utils.ts b/modules/angular2/src/test_lib/utils.ts index 1784d56d51..b6b47d37a9 100644 --- a/modules/angular2/src/test_lib/utils.ts +++ b/modules/angular2/src/test_lib/utils.ts @@ -77,6 +77,8 @@ export function stringifyElement(el): string { if (!ListWrapper.contains(_singleTagWhitelist, tagName)) { result += ``; } + } else if (DOM.isCommentNode(el)) { + result += ``; } else { result += DOM.getText(el); } diff --git a/modules/angular2/test/core/compiler/integration_spec.ts b/modules/angular2/test/core/compiler/integration_spec.ts index 21f7dae156..fe3a67df90 100644 --- a/modules/angular2/test/core/compiler/integration_spec.ts +++ b/modules/angular2/test/core/compiler/integration_spec.ts @@ -1390,6 +1390,28 @@ export function main() { }); } + describe('different proto view storages', () => { + function runWithMode(mode: string) { + return inject( + [TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => { + tcb.overrideView(MyComp, + new viewAnn.View({template: `
{{ctxProp}}
`})) + .createAsync(MyComp) + .then((rootTC) => { + rootTC.componentInstance.ctxProp = 'Hello World!'; + + rootTC.detectChanges(); + expect(rootTC.nativeElement).toHaveText('Hello World!'); + async.done(); + }); + }); + } + + it('should work with storing DOM nodes', runWithMode('cache')); + + it('should work with serializing the DOM nodes', runWithMode('nocache')); + }); + // Disabled until a solution is found, refs: // - https://github.com/angular/angular/issues/776 // - https://github.com/angular/angular/commit/81f3f32 diff --git a/modules/angular2/test/render/dom/compiler/compiler_common_tests.ts b/modules/angular2/test/render/dom/compiler/compiler_common_tests.ts index 1837798ca5..de771c42ec 100644 --- a/modules/angular2/test/render/dom/compiler/compiler_common_tests.ts +++ b/modules/angular2/test/render/dom/compiler/compiler_common_tests.ts @@ -34,6 +34,8 @@ import {SharedStylesHost} from 'angular2/src/render/dom/view/shared_styles_host' import {MockStep} from './pipeline_spec'; +import {ReferenceCloneableTemplate} from 'angular2/src/render/dom/util'; + export function runCompilerCommonTests() { describe('DomCompiler', function() { var mockStepFactory: MockStepFactory; @@ -78,8 +80,7 @@ export function runCompilerCommonTests() { {id: 'id', selector: 'custom', type: DirectiveMetadata.COMPONENT_TYPE}); compiler.compileHost(dirMetadata) .then((protoView) => { - expect(DOM.tagName(DOM.firstChild(DOM.content( - resolveInternalDomProtoView(protoView.render).rootElement))) + expect(DOM.tagName(DOM.firstChild(DOM.content(templateRoot(protoView)))) .toLowerCase()) .toEqual('custom'); expect(mockStepFactory.viewDef.directives).toEqual([dirMetadata]); @@ -95,8 +96,7 @@ export function runCompilerCommonTests() { compiler.compile( new ViewDefinition({componentId: 'someId', template: 'inline component'})) .then((protoView) => { - expect(DOM.getInnerHTML(resolveInternalDomProtoView(protoView.render).rootElement)) - .toEqual('inline component'); + expect(DOM.getInnerHTML(templateRoot(protoView))).toEqual('inline component'); async.done(); }); })); @@ -106,8 +106,7 @@ export function runCompilerCommonTests() { var compiler = createCompiler(EMPTY_STEP, null, urlData); compiler.compile(new ViewDefinition({componentId: 'someId', templateAbsUrl: 'someUrl'})) .then((protoView) => { - expect(DOM.getInnerHTML(resolveInternalDomProtoView(protoView.render).rootElement)) - .toEqual('url component'); + expect(DOM.getInnerHTML(templateRoot(protoView))).toEqual('url component'); async.done(); }); })); @@ -173,8 +172,7 @@ export function runCompilerCommonTests() { encapsulation: ViewEncapsulation.NONE })) .then((protoViewDto) => { - var domProtoView = resolveInternalDomProtoView(protoViewDto.render); - expect(DOM.getInnerHTML(domProtoView.rootElement)).toEqual(''); + expect(DOM.getInnerHTML(templateRoot(protoViewDto))).toEqual(''); expect(sharedStylesHost.getAllStyles()).toEqual(['a {};']); async.done(); }); @@ -190,8 +188,7 @@ export function runCompilerCommonTests() { encapsulation: ViewEncapsulation.EMULATED })) .then((protoViewDto) => { - var domProtoView = resolveInternalDomProtoView(protoViewDto.render); - expect(DOM.getInnerHTML(domProtoView.rootElement)).toEqual(''); + expect(DOM.getInnerHTML(templateRoot(protoViewDto))).toEqual(''); expect(sharedStylesHost.getAllStyles()).toEqual(['a {};']); async.done(); }); @@ -208,8 +205,7 @@ export function runCompilerCommonTests() { encapsulation: ViewEncapsulation.NATIVE })) .then((protoViewDto) => { - var domProtoView = resolveInternalDomProtoView(protoViewDto.render); - expect(DOM.getInnerHTML(domProtoView.rootElement)) + expect(DOM.getInnerHTML(templateRoot(protoViewDto))) .toEqual(''); expect(sharedStylesHost.getAllStyles()).toEqual([]); async.done(); @@ -259,6 +255,11 @@ export function runCompilerCommonTests() { }); } +function templateRoot(protoViewDto: ProtoViewDto) { + var pv = resolveInternalDomProtoView(protoViewDto.render); + return (pv.cloneableTemplate).templateRoot; +} + class MockStepFactory extends CompileStepFactory { steps: List; subTaskPromises: List>; diff --git a/modules/angular2/test/render/dom/util_spec.ts b/modules/angular2/test/render/dom/util_spec.ts new file mode 100644 index 0000000000..c621e9688a --- /dev/null +++ b/modules/angular2/test/render/dom/util_spec.ts @@ -0,0 +1,97 @@ +import { + AsyncTestCompleter, + beforeEach, + ddescribe, + describe, + el, + expect, + iit, + inject, + it, + xit, + beforeEachBindings, + SpyObject, +} from 'angular2/test_lib'; + +import {DOM} from 'angular2/src/dom/dom_adapter'; +import { + prepareTemplateForClone, + ReferenceCloneableTemplate, + SerializedCloneableTemplate +} from 'angular2/src/render/dom/util'; + +export function main() { + describe('Dom util', () => { + + describe('prepareTemplateForClone', () => { + it('should use a reference for small templates', () => { + var t = DOM.createTemplate(''); + var ct = prepareTemplateForClone(t); + expect((ct).templateRoot).toBe(t); + }); + + it('should use a reference for big templates with a force comment', () => { + var templateString = ''; + for (var i = 0; i < 100; i++) { + templateString += '
'; + } + var t = DOM.createTemplate(templateString); + var ct = prepareTemplateForClone(t); + expect((ct).templateRoot).toBe(t); + }); + + it('should serialize for big templates', () => { + var templateString = ''; + for (var i = 0; i < 100; i++) { + templateString += '
'; + } + var t = DOM.createTemplate(templateString); + var ct = prepareTemplateForClone(t); + expect((ct).templateString).toEqual(templateString); + }); + + it('should serialize for templates with the force comment', () => { + var templateString = ''; + var t = DOM.createTemplate(templateString); + var ct = prepareTemplateForClone(t); + expect((ct).templateString).toEqual(templateString); + }); + }); + + describe('ReferenceCloneableTemplate', () => { + it('should return template.content nodes (no import)', () => { + var t = DOM.createTemplate('a'); + var ct = new ReferenceCloneableTemplate(t); + var clone = ct.clone(false); + expect(clone).not.toBe(DOM.content(t)); + expect(DOM.getText(DOM.firstChild(clone))).toEqual('a'); + }); + + it('should return template.content nodes (import into doc)', () => { + var t = DOM.createTemplate('a'); + var ct = new ReferenceCloneableTemplate(t); + var clone = ct.clone(true); + expect(clone).not.toBe(DOM.content(t)); + expect(DOM.getText(DOM.firstChild(clone))).toEqual('a'); + }); + }); + + describe('SerializedCloneableTemplate', () => { + it('should return template.content nodes (no import)', () => { + var t = DOM.createTemplate('a'); + var ct = new SerializedCloneableTemplate(t); + var clone = ct.clone(false); + expect(clone).not.toBe(DOM.content(t)); + expect(DOM.getText(DOM.firstChild(clone))).toEqual('a'); + }); + + it('should return template.content nodes (import into doc)', () => { + var t = DOM.createTemplate('a'); + var ct = new SerializedCloneableTemplate(t); + var clone = ct.clone(true); + expect(clone).not.toBe(DOM.content(t)); + expect(DOM.getText(DOM.firstChild(clone))).toEqual('a'); + }); + }); + }); +} \ No newline at end of file diff --git a/modules/angular2/test/render/dom/view/proto_view_merger_integration_spec.ts b/modules/angular2/test/render/dom/view/proto_view_merger_integration_spec.ts index 68a5f2ba08..9df5c4d806 100644 --- a/modules/angular2/test/render/dom/view/proto_view_merger_integration_spec.ts +++ b/modules/angular2/test/render/dom/view/proto_view_merger_integration_spec.ts @@ -3,6 +3,7 @@ import { beforeEach, ddescribe, describe, + xdescribe, el, expect, iit, @@ -27,8 +28,8 @@ import { } from 'angular2/src/render/api'; import {DOM} from 'angular2/src/dom/dom_adapter'; -import {cloneAndQueryProtoView} from 'angular2/src/render/dom/util'; -import {resolveInternalDomProtoView} from 'angular2/src/render/dom/view/proto_view'; +import {cloneAndQueryProtoView, ReferenceCloneableTemplate} from 'angular2/src/render/dom/util'; +import {resolveInternalDomProtoView, DomProtoView} from 'angular2/src/render/dom/view/proto_view'; import {ProtoViewBuilder} from 'angular2/src/render/dom/view/proto_view_builder'; import {ElementSchemaRegistry} from 'angular2/src/render/dom/schema/element_schema_registry'; @@ -90,23 +91,23 @@ export function main() { [''])); it('should project static text', - runAndAssert( - 'root', ['b', 'A()'], - ['A(b)'])); + runAndAssert('root', ['b', 'A()'], [ + 'A(b)' + ])); it('should project text interpolation', - runAndAssert( - 'root', ['{{b}}', 'A()'], - ['A({0})'])); + runAndAssert('root', ['{{b}}', 'A()'], [ + 'A({0})' + ])); it('should project text interpolation to elements without bindings', runAndAssert('root', ['{{b}}', '
'], [ - '
{0}
' + '
{0}
' ])); it('should project elements', runAndAssert('root', ['
', 'A()'], [ - 'A(
)
' + 'A(
)
' ])); it('should project elements using the selector', @@ -117,14 +118,26 @@ export function main() { 'A()' ], [ - 'A(
a
b
)
' + 'A(
a
b
)
' ])); it('should reproject', runAndAssert( 'root', ['x', 'A()', 'B()'], [ - 'A(B(x))' + 'A(B(x))' + ])); + + it('should reproject text interpolation to sibling text nodes', + runAndAssert( + 'root', + [ + '{{x}}', + 'A())', + 'B()' + ], + [ + 'B(A({0})))' ])); it('should reproject by combining selectors', @@ -136,7 +149,7 @@ export function main() { 'B()' ], [ - 'A(B(
)
)
' + 'A(B(
)
)
' ])); it('should keep non projected embedded views as fragments (so that they can be moved manually)', @@ -147,14 +160,14 @@ export function main() { it('should project embedded views and match the template element', runAndAssert( 'root', ['', 'A()'], [ - 'A()', + 'A()', 'b' ])); it('should project nodes using the ng-content in embedded views', runAndAssert('root', ['b', 'A()'], [ 'A()', - 'b' + 'b' ])); it('should allow to use wildcard selector after embedded view with non wildcard selector', @@ -165,8 +178,8 @@ export function main() { 'A(, )' ], [ - 'A(, b)', - '
a
' + 'A(, b)', + '
a
' ])); }); @@ -208,7 +221,7 @@ export function main() { '' ], [ - '' + '' ])); }); @@ -227,7 +240,7 @@ export function main() { '' ], [ - '
{1}
{0}
' + '
{1}
{0}
' ])); }); @@ -252,7 +265,7 @@ export function main() { tb.merge([rootProtoViewDto, componentProtoViewDto]) .then(mergeMappings => { var domPv = resolveInternalDomProtoView(mergeMappings.mergedProtoViewRef); - expect(DOM.getInnerHTML(domPv.rootElement)) + expect(DOM.getInnerHTML(templateRoot(domPv))) .toEqual(''); async.done(); }); @@ -264,6 +277,10 @@ export function main() { }); } +function templateRoot(pv: DomProtoView) { + return (pv.cloneableTemplate).templateRoot; +} + function runAndAssert(hostElementName: string, componentTemplates: string[], expectedFragments: string[]) { var useNativeEncapsulation = hostElementName.startsWith('native-'); diff --git a/modules/angular2/test/web-workers/worker/renderer_spec.ts b/modules/angular2/test/web-workers/worker/renderer_spec.ts index 6b56d16615..fea5f210d5 100644 --- a/modules/angular2/test/web-workers/worker/renderer_spec.ts +++ b/modules/angular2/test/web-workers/worker/renderer_spec.ts @@ -34,11 +34,12 @@ import { RenderViewWithFragmentsStore, WorkerRenderViewRef } from 'angular2/src/web-workers/shared/render_view_with_fragments_store'; -import {resolveInternalDomProtoView} from 'angular2/src/render/dom/view/proto_view'; +import {resolveInternalDomProtoView, DomProtoView} from 'angular2/src/render/dom/view/proto_view'; import {someComponent} from '../../render/dom/dom_renderer_integration_spec'; import {WebWorkerMain} from 'angular2/src/web-workers/ui/impl'; import {AnchorBasedAppRootUrl} from 'angular2/src/services/anchor_based_app_root_url'; import {MockMessageBus, MockMessageBusSink, MockMessageBusSource} from './worker_test_util'; +import {ReferenceCloneableTemplate} from 'angular2/src/render/dom/util'; export function main() { function createBroker(workerSerializer: Serializer, uiSerializer: Serializer, tb: DomTestbed, @@ -103,7 +104,7 @@ export function main() { compiler.compileHost(dirMetadata) .then((protoView) => { expect(DOM.tagName(DOM.firstChild(DOM.content( - resolveWebWorkerRef(protoView.render).rootElement))) + templateRoot(resolveWebWorkerRef(protoView.render))))) .toLowerCase()) .toEqual('custom'); expect(protoView).not.toBeNull(); @@ -297,6 +298,10 @@ class WorkerTestRootView extends TestRootView { } } +function templateRoot(pv: DomProtoView) { + return (pv.cloneableTemplate).templateRoot; +} + function createSerializer(protoViewRefStore: RenderProtoViewRefStore, renderViewStore: RenderViewWithFragmentsStore): Serializer { var injector = createTestInjector([