diff --git a/packages/core/src/render3/component_ref.ts b/packages/core/src/render3/component_ref.ts index a3d8ad2131..f6fe2d964d 100644 --- a/packages/core/src/render3/component_ref.ts +++ b/packages/core/src/render3/component_ref.ts @@ -30,7 +30,7 @@ import {ComponentDef} from './interfaces/definition'; import {TContainerNode, TElementContainerNode, TElementNode} from './interfaces/node'; import {RNode, RendererFactory3, domRendererFactory3, isProceduralRenderer} from './interfaces/renderer'; import {LView, LViewFlags, RootContext, TVIEW} from './interfaces/view'; -import {enterView, leaveView} from './state'; +import {enterView, leaveView, namespaceHTMLInternal} from './state'; import {defaultScheduler} from './util/misc_utils'; import {getTNode} from './util/view_utils'; import {createElementRef} from './view_engine_compatibility'; @@ -140,6 +140,9 @@ export class ComponentFactory extends viewEngine_ComponentFactory { rootViewInjector.get(RendererFactory2, domRendererFactory3) as RendererFactory3; const sanitizer = rootViewInjector.get(Sanitizer, null); + // Ensure that the namespace for the root node is correct, + // otherwise the browser might not render out the element properly. + namespaceHTMLInternal(); const hostRNode = isInternalRootView ? elementCreate(this.selector, rendererFactory.createRenderer(null, this.componentDef)) : locateHostElement(rendererFactory, rootSelectorOrNode); diff --git a/packages/core/src/render3/state.ts b/packages/core/src/render3/state.ts index 4d89ee54ac..57e8b54b3d 100644 --- a/packages/core/src/render3/state.ts +++ b/packages/core/src/render3/state.ts @@ -537,12 +537,20 @@ export function ɵɵnamespaceMathML() { } /** - * Sets the namespace used to create elements no `null`, which forces element creation to use + * Sets the namespace used to create elements to `null`, which forces element creation to use * `createElement` rather than `createElementNS`. * * @codeGenApi */ export function ɵɵnamespaceHTML() { + namespaceHTMLInternal(); +} + +/** + * Sets the namespace used to create elements to `null`, which forces element creation to use + * `createElement` rather than `createElementNS`. + */ +export function namespaceHTMLInternal() { _currentNamespace = null; } diff --git a/packages/core/test/acceptance/view_container_ref_spec.ts b/packages/core/test/acceptance/view_container_ref_spec.ts index 0db09a7467..b9de42aa3d 100644 --- a/packages/core/test/acceptance/view_container_ref_spec.ts +++ b/packages/core/test/acceptance/view_container_ref_spec.ts @@ -1049,6 +1049,43 @@ describe('ViewContainerRef', () => { expect(() => fixture.componentRef.destroy()).not.toThrow(); }); + it('should create the root node in the correct namespace when previous node is SVG', () => { + @Component({ + template: ` +
Some random content
+ + + ` + }) + class TestComp { + constructor( + public viewContainerRef: ViewContainerRef, + public componentFactoryResolver: ComponentFactoryResolver) {} + } + + @Component({selector: 'dynamic-comp', template: ''}) + class DynamicComponent { + } + + @NgModule({declarations: [DynamicComponent], entryComponents: [DynamicComponent]}) + class DeclaresDynamicComponent { + } + + TestBed.configureTestingModule( + {imports: [DeclaresDynamicComponent], declarations: [TestComp]}); + const fixture = TestBed.createComponent(TestComp); + + // Note: it's important that we **don't** call `fixture.detectChanges` between here and + // the component being created, because running change detection will reset Ivy's + // namespace state which will make the test pass. + + const {viewContainerRef, componentFactoryResolver} = fixture.componentInstance; + const componentRef = viewContainerRef.createComponent( + componentFactoryResolver.resolveComponentFactory(DynamicComponent)); + const element = componentRef.location.nativeElement; + expect((element.namespaceURI || '').toLowerCase()).not.toContain('svg'); + }); + }); describe('insertion points and declaration points', () => { diff --git a/packages/core/test/bundling/cyclic_import/bundle.golden_symbols.json b/packages/core/test/bundling/cyclic_import/bundle.golden_symbols.json index ad90414efd..ce7aaffd47 100644 --- a/packages/core/test/bundling/cyclic_import/bundle.golden_symbols.json +++ b/packages/core/test/bundling/cyclic_import/bundle.golden_symbols.json @@ -581,6 +581,9 @@ { "name": "matchTemplateAttribute" }, + { + "name": "namespaceHTMLInternal" + }, { "name": "nativeAppendChild" }, diff --git a/packages/core/test/bundling/hello_world/bundle.golden_symbols.json b/packages/core/test/bundling/hello_world/bundle.golden_symbols.json index ba58c7eaae..f694748d27 100644 --- a/packages/core/test/bundling/hello_world/bundle.golden_symbols.json +++ b/packages/core/test/bundling/hello_world/bundle.golden_symbols.json @@ -386,6 +386,9 @@ { "name": "locateHostElement" }, + { + "name": "namespaceHTMLInternal" + }, { "name": "nativeAppendChild" }, diff --git a/packages/core/test/bundling/todo/bundle.golden_symbols.json b/packages/core/test/bundling/todo/bundle.golden_symbols.json index 0d20b4a710..2eb9133154 100644 --- a/packages/core/test/bundling/todo/bundle.golden_symbols.json +++ b/packages/core/test/bundling/todo/bundle.golden_symbols.json @@ -1244,6 +1244,9 @@ { "name": "matchTemplateAttribute" }, + { + "name": "namespaceHTMLInternal" + }, { "name": "nativeAppendChild" },