Skip to content

Commit fb9163a

Browse files
atscottAndrewKushnir
authored andcommitted
fix(core): consistently use namespace short name rather than URI (#44766)
`Renderer2` APIs expect to be called with the namespace name rather than the namespace URI. Rather than passing around the URI and having to account for different calling contexts, this change consistently uses the namespace short names. Importantly, the URI was only used in `component_ref.ts` `create` (because `getNamespace returned the URIs`) and `createElementNode` in `node_manipulation.ts` (because `getNamespaceUri` also used the URIs). In contrast, attributes would use the _short names instead of URIs_ (see `setUpAttributes` in `attrs_utils.ts`). These names are pulled directly from the attribute, i.e. `xhtml:href` and not converted to URI. This dichotomy is confusing and unnecessary. The change here aligns the two approaches in order to provide consistently throughout the system. This relates to #44766 because the `createElementNode` was calling the `AnimationRenderer.createElement` which delegates to the `ServerRenderer`, which in turn was only set up to expect short names. As a result, the `NAMESPACE_URIS` lookup failed and `Domino` created the `svg` as a regular `Element` which does not have a `styles` property. resolves #44766 PR Close #44766
1 parent 37e5196 commit fb9163a

File tree

7 files changed

+21
-29
lines changed

7 files changed

+21
-29
lines changed

packages/core/src/render3/namespaces.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,13 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88

9-
export const SVG_NAMESPACE = 'http://www.w3.org/2000/svg';
10-
export const MATH_ML_NAMESPACE = 'http://www.w3.org/1998/MathML/';
9+
export const SVG_NAMESPACE = 'svg';
10+
export const SVG_NAMESPACE_URI = 'http://www.w3.org/2000/svg';
11+
export const MATH_ML_NAMESPACE = 'math';
12+
export const MATH_ML_NAMESPACE_URI = 'http://www.w3.org/1998/MathML/';
13+
14+
export function getNamespaceUri(namespace: string): string|null {
15+
const name = namespace.toLowerCase();
16+
return name === SVG_NAMESPACE ? SVG_NAMESPACE_URI :
17+
(name === MATH_ML_NAMESPACE ? MATH_ML_NAMESPACE_URI : null);
18+
}

packages/core/src/render3/node_manipulation.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import {isProceduralRenderer, ProceduralRenderer3, Renderer3, unusedValueExportT
2525
import {RComment, RElement, RNode, RText} from './interfaces/renderer_dom';
2626
import {isLContainer, isLView} from './interfaces/type_checks';
2727
import {CHILD_HEAD, CLEANUP, DECLARATION_COMPONENT_VIEW, DECLARATION_LCONTAINER, DestroyHookData, FLAGS, HookData, HookFn, HOST, LView, LViewFlags, NEXT, PARENT, QUERIES, RENDERER, T_HOST, TVIEW, TView, TViewType, unusedValueExportToPlacateAjd as unused5} from './interfaces/view';
28+
import {getNamespaceUri} from './namespaces';
2829
import {assertTNodeType} from './node_assert';
2930
import {profiler, ProfilerEvent} from './profiler';
3031
import {getLViewParent} from './util/view_traversal_utils';
@@ -132,8 +133,9 @@ export function createElementNode(
132133
if (isProceduralRenderer(renderer)) {
133134
return renderer.createElement(name, namespace);
134135
} else {
135-
return namespace === null ? renderer.createElement(name) :
136-
renderer.createElementNS(namespace, name);
136+
const namespaceUri = namespace !== null ? getNamespaceUri(namespace) : null;
137+
return namespaceUri === null ? renderer.createElement(name) :
138+
renderer.createElementNS(namespaceUri, name);
137139
}
138140
}
139141

packages/core/test/acceptance/i18n_spec.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -542,10 +542,6 @@ describe('runtime i18n', () => {
542542
TestBed.configureTestingModule({
543543
providers: [
544544
{provide: DOCUMENT, useFactory: _document, deps: []},
545-
// TODO(FW-811): switch back to default server renderer (i.e. remove the line
546-
// below) once it starts to support Ivy namespace format (URIs) correctly. For
547-
// now, use `DomRenderer` that supports Ivy namespace format.
548-
{provide: RendererFactory2, useClass: DomRendererFactory2}
549545
],
550546
});
551547
});

packages/core/test/acceptance/view_container_ref_spec.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -197,10 +197,6 @@ describe('ViewContainerRef', () => {
197197
declarations: [TestComp, SvgComp, MathMLComp],
198198
providers: [
199199
{provide: DOCUMENT, useFactory: _document, deps: []},
200-
// TODO(FW-811): switch back to default server renderer (i.e. remove the line below)
201-
// once it starts to support Ivy namespace format (URIs) correctly. For now, use
202-
// `DomRenderer` that supports Ivy namespace format.
203-
{provide: RendererFactory2, useClass: DomRendererFactory2}
204200
],
205201
});
206202
const fixture = TestBed.createComponent(TestComp);

packages/platform-browser/src/dom/dom_renderer.ts

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export const NAMESPACE_URIS: {[ns: string]: string} = {
1717
'xlink': 'http://www.w3.org/1999/xlink',
1818
'xml': 'http://www.w3.org/XML/1998/namespace',
1919
'xmlns': 'http://www.w3.org/2000/xmlns/',
20+
'math': 'http://www.w3.org/1998/MathML/',
2021
};
2122

2223
const COMPONENT_REGEX = /%COMP%/g;
@@ -144,9 +145,7 @@ class DefaultDomRenderer2 implements Renderer2 {
144145

145146
createElement(name: string, namespace?: string): any {
146147
if (namespace) {
147-
// In cases where Ivy (not ViewEngine) is giving us the actual namespace, the look up by key
148-
// will result in undefined, so we just return the namespace here.
149-
return document.createElementNS(NAMESPACE_URIS[namespace] || namespace, name);
148+
return document.createElementNS(NAMESPACE_URIS[namespace], name);
150149
}
151150

152151
return document.createElement(name);
@@ -199,8 +198,6 @@ class DefaultDomRenderer2 implements Renderer2 {
199198
setAttribute(el: any, name: string, value: string, namespace?: string): void {
200199
if (namespace) {
201200
name = namespace + ':' + name;
202-
// TODO(FW-811): Ivy may cause issues here because it's passing around
203-
// full URIs for namespaces, therefore this lookup will fail.
204201
const namespaceUri = NAMESPACE_URIS[namespace];
205202
if (namespaceUri) {
206203
el.setAttributeNS(namespaceUri, name, value);
@@ -214,15 +211,10 @@ class DefaultDomRenderer2 implements Renderer2 {
214211

215212
removeAttribute(el: any, name: string, namespace?: string): void {
216213
if (namespace) {
217-
// TODO(FW-811): Ivy may cause issues here because it's passing around
218-
// full URIs for namespaces, therefore this lookup will fail.
219214
const namespaceUri = NAMESPACE_URIS[namespace];
220215
if (namespaceUri) {
221216
el.removeAttributeNS(namespaceUri, name);
222217
} else {
223-
// TODO(FW-811): Since ivy is passing around full URIs for namespaces
224-
// this could result in properties like `http://www.w3.org/2000/svg:cx="123"`,
225-
// which is wrong.
226218
el.removeAttribute(`${namespace}:${name}`);
227219
}
228220
} else {

packages/platform-server/src/server_renderer.ts

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,6 @@ class DefaultServerRenderer2 implements Renderer2 {
7272
createElement(name: string, namespace?: string, debugInfo?: any): any {
7373
if (namespace) {
7474
const doc = this.document || getDOM().getDefaultDocument();
75-
// TODO(FW-811): Ivy may cause issues here because it's passing around
76-
// full URIs for namespaces, therefore this lookup will fail.
7775
return doc.createElementNS(NAMESPACE_URIS[namespace], name);
7876
}
7977

@@ -131,8 +129,6 @@ class DefaultServerRenderer2 implements Renderer2 {
131129

132130
setAttribute(el: any, name: string, value: string, namespace?: string): void {
133131
if (namespace) {
134-
// TODO(FW-811): Ivy may cause issues here because it's passing around
135-
// full URIs for namespaces, therefore this lookup will fail.
136132
el.setAttributeNS(NAMESPACE_URIS[namespace], namespace + ':' + name, value);
137133
} else {
138134
el.setAttribute(name, value);
@@ -141,8 +137,6 @@ class DefaultServerRenderer2 implements Renderer2 {
141137

142138
removeAttribute(el: any, name: string, namespace?: string): void {
143139
if (namespace) {
144-
// TODO(FW-811): Ivy may cause issues here because it's passing around
145-
// full URIs for namespaces, therefore this lookup will fail.
146140
el.removeAttributeNS(NAMESPACE_URIS[namespace], name);
147141
} else {
148142
el.removeAttribute(name);

packages/platform-server/test/integration_spec.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,11 @@ class SVGServerModule {
193193

194194
@Component({
195195
selector: 'app',
196-
template: `<div [@myAnimation]="state">{{text}}</div>`,
196+
template: `
197+
<div [@myAnimation]="state">
198+
<svg *ngIf="true"></svg>
199+
{{text}}
200+
</div>`,
197201
animations: [trigger(
198202
'myAnimation',
199203
[

0 commit comments

Comments
 (0)