Revert "feat(ivy): added namespaced attributes (#23899)"

This reverts commit d6989c80d3.
This commit is contained in:
Victor Berchet 2018-06-06 13:38:20 -07:00
parent 3128b26e5c
commit 07b4c8be42
6 changed files with 43 additions and 155 deletions

View File

@ -260,11 +260,8 @@ export function injectAttribute(attrNameToInject: string): string|undefined {
const attrs = tElement.attrs; const attrs = tElement.attrs;
if (attrs) { if (attrs) {
for (let i = 0; i < attrs.length; i = i + 2) { for (let i = 0; i < attrs.length; i = i + 2) {
let attrName = attrs[i]; const attrName = attrs[i];
if (attrName === AttributeMarker.SELECT_ONLY) break; if (attrName === AttributeMarker.SELECT_ONLY) break;
if (attrName === 0) { // NS.FULL
attrName = attrs[i += 2];
}
if (attrName == attrNameToInject) { if (attrName == attrNameToInject) {
return attrs[i + 1] as string; return attrs[i + 1] as string;
} }

View File

@ -842,28 +842,15 @@ export function createTView(
function setUpAttributes(native: RElement, attrs: TAttributes): void { function setUpAttributes(native: RElement, attrs: TAttributes): void {
const isProc = isProceduralRenderer(renderer); const isProc = isProceduralRenderer(renderer);
for (let i = 0; i < attrs.length; i += 2) { for (let i = 0; i < attrs.length; i += 2) {
let attrName = attrs[i]; const attrName = attrs[i];
if (attrName === 0) { // NS.FULL if (attrName === AttributeMarker.SELECT_ONLY) break;
// Namespaced attribute if (attrName !== NG_PROJECT_AS_ATTR_NAME) {
const attrNS = attrs[i + 1] as string; const attrVal = attrs[i + 1];
attrName = attrs[i + 2] as string; ngDevMode && ngDevMode.rendererSetAttribute++;
const attrVal = attrs[i + 3] as string; isProc ?
i += 2; (renderer as ProceduralRenderer3)
if (isProc) { .setAttribute(native, attrName as string, attrVal as string) :
(renderer as ProceduralRenderer3).setAttribute(native, attrName, attrVal, attrNS); native.setAttribute(attrName as string, attrVal as string);
} else {
native.setAttributeNS(attrNS, attrName, attrVal);
}
} else {
if (attrName === AttributeMarker.SELECT_ONLY) break;
if (attrName !== NG_PROJECT_AS_ATTR_NAME) {
const attrVal = attrs[i + 1];
ngDevMode && ngDevMode.rendererSetAttribute++;
isProc ?
(renderer as ProceduralRenderer3)
.setAttribute(native, attrName as string, attrVal as string) :
native.setAttribute(attrName as string, attrVal as string);
}
} }
} }
} }
@ -1506,8 +1493,7 @@ function generateInitialInputs(
const attrs = tNode.attrs !; const attrs = tNode.attrs !;
for (let i = 0; i < attrs.length; i += 2) { for (let i = 0; i < attrs.length; i += 2) {
const first = attrs[i]; const attrName = attrs[i];
const attrName = first === 0 ? attrs[i += 2] : first; // 0 = NS.FULL
const minifiedInputName = inputs[attrName]; const minifiedInputName = inputs[attrName];
const attrValue = attrs[i + 1]; const attrValue = attrs[i + 1];
@ -1920,7 +1906,7 @@ function appendToProjectionNode(
* - 1 based index of the selector from the {@link projectionDef} * - 1 based index of the selector from the {@link projectionDef}
*/ */
export function projection( export function projection(
nodeIndex: number, localIndex: number, selectorIndex: number = 0, attrs?: TAttributes): void { nodeIndex: number, localIndex: number, selectorIndex: number = 0, attrs?: string[]): void {
const node = createLNode( const node = createLNode(
nodeIndex, TNodeType.Projection, null, null, attrs || null, {head: null, tail: null}); nodeIndex, TNodeType.Projection, null, null, attrs || null, {head: null, tail: null});

View File

@ -5,6 +5,7 @@
* Use of this source code is governed by an MIT-style license that can be * Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
import {LContainer} from './container'; import {LContainer} from './container';
import {LInjector} from './injector'; import {LInjector} from './injector';
import {LProjection} from './projection'; import {LProjection} from './projection';
@ -13,16 +14,6 @@ import {RElement, RNode, RText} from './renderer';
import {LView, TData, TView} from './view'; import {LView, TData, TView} from './view';
/**
* Namespace attribute flags.
*/
export const enum NS {
/**
* Use the next value as the full namespaces URI, the values after that
* are then the name and the value, respectively.
*/
FULL = 0,
}
/** /**
* TNodeType corresponds to the TNode.type property. It contains information * TNodeType corresponds to the TNode.type property. It contains information
@ -188,7 +179,7 @@ export const enum AttributeMarker {
* - attribute names and values * - attribute names and values
* - special markers acting as flags to alter attributes processing. * - special markers acting as flags to alter attributes processing.
*/ */
export type TAttributes = (string | AttributeMarker | NS)[]; export type TAttributes = (string | AttributeMarker)[];
/** /**
* LNode binding data (flyweight) for a particular node that is shared between all templates * LNode binding data (flyweight) for a particular node that is shared between all templates

View File

@ -106,12 +106,8 @@ function findAttrIndexInNode(name: string, attrs: TAttributes | null): number {
if (attrs === null) return -1; if (attrs === null) return -1;
for (let i = 0; i < attrs.length; i += step) { for (let i = 0; i < attrs.length; i += step) {
const attrName = attrs[i]; const attrName = attrs[i];
if (attrName === 0) { if (attrName === name) return i;
// NS.FULL if (attrName === AttributeMarker.SELECT_ONLY) {
step = 2;
} else if (attrName === name) {
return i;
} else if (attrName === AttributeMarker.SELECT_ONLY) {
step = 1; step = 1;
} }
} }

View File

@ -11,7 +11,7 @@ import {NgForOfContext} from '@angular/common';
import {RenderFlags, directiveInject} from '../../src/render3'; import {RenderFlags, directiveInject} from '../../src/render3';
import {defineComponent} from '../../src/render3/definition'; import {defineComponent} from '../../src/render3/definition';
import {bind, container, elementAttribute, elementClass, elementEnd, elementProperty, elementStart, elementStyle, elementStyleNamed, interpolation1, renderTemplate, setHtmlNS, setSvgNS, text, textBinding} from '../../src/render3/instructions'; import {bind, container, elementAttribute, elementClass, elementEnd, elementProperty, elementStart, elementStyle, elementStyleNamed, interpolation1, renderTemplate, setHtmlNS, setSvgNS, text, textBinding} from '../../src/render3/instructions';
import {LElementNode, LNode, NS} from '../../src/render3/interfaces/node'; import {LElementNode, LNode} from '../../src/render3/interfaces/node';
import {RElement, domRendererFactory3} from '../../src/render3/interfaces/renderer'; import {RElement, domRendererFactory3} from '../../src/render3/interfaces/renderer';
import {TrustedString, bypassSanitizationTrustHtml, bypassSanitizationTrustResourceUrl, bypassSanitizationTrustScript, bypassSanitizationTrustStyle, bypassSanitizationTrustUrl, sanitizeHtml, sanitizeResourceUrl, sanitizeScript, sanitizeStyle, sanitizeUrl} from '../../src/sanitization/sanitization'; import {TrustedString, bypassSanitizationTrustHtml, bypassSanitizationTrustResourceUrl, bypassSanitizationTrustScript, bypassSanitizationTrustStyle, bypassSanitizationTrustUrl, sanitizeHtml, sanitizeResourceUrl, sanitizeScript, sanitizeStyle, sanitizeUrl} from '../../src/sanitization/sanitization';
import {Sanitizer, SecurityContext} from '../../src/sanitization/security'; import {Sanitizer, SecurityContext} from '../../src/sanitization/security';
@ -91,43 +91,6 @@ describe('instructions', () => {
rendererSetAttribute: 2 rendererSetAttribute: 2
}); });
}); });
it('should use sanitizer function even on elements with namespaced attributes', () => {
const t = new TemplateFixture(() => {
elementStart(0, 'div', [
NS.FULL,
'http://www.example.com/2004/test',
'whatever',
'abc',
]);
elementEnd();
});
t.update(() => elementAttribute(0, 'title', 'javascript:true', sanitizeUrl));
let standardHTML = '<div whatever="abc" title="unsafe:javascript:true"></div>';
let ieHTML = '<div title="unsafe:javascript:true" whatever="abc"></div>';
expect([standardHTML, ieHTML]).toContain(t.html);
t.update(
() => elementAttribute(
0, 'title', bypassSanitizationTrustUrl('javascript:true'), sanitizeUrl));
standardHTML = '<div whatever="abc" title="javascript:true"></div>';
ieHTML = '<div title="javascript:true" whatever="abc"></div>';
expect([standardHTML, ieHTML]).toContain(t.html);
expect(ngDevMode).toHaveProperties({
firstTemplatePass: 1,
tNode: 2,
tView: 1,
rendererCreateElement: 1,
rendererSetAttribute: 2
});
});
}); });
describe('elementProperty', () => { describe('elementProperty', () => {
@ -445,11 +408,6 @@ describe('instructions', () => {
// height="300" // height="300"
'height', 'height',
'300', '300',
// test:title="abc"
NS.FULL,
'http://www.example.com/2014/test',
'title',
'abc',
]); ]);
elementStart(2, 'circle', ['cx', '200', 'cy', '150', 'fill', '#0000ff']); elementStart(2, 'circle', ['cx', '200', 'cy', '150', 'fill', '#0000ff']);
elementEnd(); elementEnd();
@ -461,71 +419,12 @@ describe('instructions', () => {
// Most browsers will print <circle></circle>, some will print <circle />, both are valid // Most browsers will print <circle></circle>, some will print <circle />, both are valid
const standardHTML = const standardHTML =
'<div id="container"><svg id="display" width="400" height="300" title="abc"><circle cx="200" cy="150" fill="#0000ff"></circle></svg></div>'; '<div id="container"><svg id="display" width="400" height="300"><circle cx="200" cy="150" fill="#0000ff"></circle></svg></div>';
const ie11HTML = const ie11HTML =
'<div id="container"><svg xmlns="http://www.w3.org/2000/svg" xmlns:NS1="http://www.example.com/2014/test" NS1:title="abc" id="display" width="400" height="300"><circle fill="#0000ff" cx="200" cy="150" /></svg></div>'; '<div id="container"><svg xmlns="http://www.w3.org/2000/svg" id="display" width="400" height="300"><circle fill="#0000ff" cx="200" cy="150" /></svg></div>';
expect([standardHTML, ie11HTML]).toContain(t.html); expect([standardHTML, ie11HTML]).toContain(t.html);
}); });
it('should set an attribute with a namespace', () => {
const t = new TemplateFixture(() => {
elementStart(0, 'div', [
'id',
'container',
// test:title="abc"
NS.FULL,
'http://www.example.com/2014/test',
'title',
'abc',
]);
elementEnd();
});
const standardHTML = '<div id="container" title="abc"></div>';
const ie11HTML =
'<div id="container" xmlns:NS1="https://www.example.com/2014/test" NS1:title="abc"></div>';
expect([standardHTML, ie11HTML]).toContain(t.html);
});
it('should set attributes including more than one namespaced attribute', () => {
const t = new TemplateFixture(() => {
elementStart(0, 'div', [
'id',
'container',
// NS1:title="abc"
NS.FULL,
'http://www.example.com/2014/test',
'title',
'abc',
// style="background: #dead11"
'style',
'background: #dead11',
// NS1:whatever="wee"
NS.FULL,
'http://www.example.com/2014/test',
'whatever',
'wee',
// NS2:shazbot="wocka wocka"
NS.FULL,
'http://www.whatever.com/2016/blah',
'shazbot',
'wocka wocka',
]);
elementEnd();
});
const standardHTML =
'<div id="container" title="abc" style="background: #dead11" whatever="wee" shazbot="wocka wocka"></div>';
const ieHTML =
'<div id="container" style="background: rgb(222, 173, 17);" title="abc" whatever="wee" shazbot="wocka wocka"></div>';
expect([standardHTML, ieHTML]).toContain(t.html);
});
}); });
}); });

View File

@ -28,14 +28,23 @@ import {NAMESPACE_URIS} from '../../src/dom/dom_renderer';
describe('setAttribute', () => { describe('setAttribute', () => {
describe('with namespace', () => { describe('with namespace', () => {
it('xmlns', () => shouldSetAttributeWithNs('xmlns'));
it('xml', () => shouldSetAttributeWithNs('xml')); it('xml', () => shouldSetAttributeWithNs('xml'));
it('svg', () => shouldSetAttributeWithNs('svg')); it('svg', () => shouldSetAttributeWithNs('svg'));
it('xhtml', () => shouldSetAttributeWithNs('xhtml')); it('xhtml', () => shouldSetAttributeWithNs('xhtml'));
it('xlink', () => shouldSetAttributeWithNs('xlink')); it('xlink', () => shouldSetAttributeWithNs('xlink'));
it('custom', () => shouldSetAttributeWithNs('custom'));
it('unknown', () => {
const div = document.createElement('div');
expect(div.hasAttribute('unknown:name')).toBe(false);
renderer.setAttribute(div, 'name', 'value', 'unknown');
expect(div.getAttribute('unknown:name')).toBe('value');
});
function shouldSetAttributeWithNs(namespace: string): void { function shouldSetAttributeWithNs(namespace: string): void {
const namespaceUri = NAMESPACE_URIS[namespace] || namespace; const namespaceUri = NAMESPACE_URIS[namespace];
const div = document.createElement('div'); const div = document.createElement('div');
expect(div.hasAttributeNS(namespaceUri, 'name')).toBe(false); expect(div.hasAttributeNS(namespaceUri, 'name')).toBe(false);
@ -48,16 +57,26 @@ import {NAMESPACE_URIS} from '../../src/dom/dom_renderer';
describe('removeAttribute', () => { describe('removeAttribute', () => {
describe('with namespace', () => { describe('with namespace', () => {
it('xmlns', () => shouldRemoveAttributeWithNs('xmlns'));
it('xml', () => shouldRemoveAttributeWithNs('xml')); it('xml', () => shouldRemoveAttributeWithNs('xml'));
it('svg', () => shouldRemoveAttributeWithNs('svg')); it('svg', () => shouldRemoveAttributeWithNs('svg'));
it('xhtml', () => shouldRemoveAttributeWithNs('xhtml')); it('xhtml', () => shouldRemoveAttributeWithNs('xhtml'));
it('xlink', () => shouldRemoveAttributeWithNs('xlink')); it('xlink', () => shouldRemoveAttributeWithNs('xlink'));
it('custom', () => shouldRemoveAttributeWithNs('custom'));
it('unknown', () => {
const div = document.createElement('div');
div.setAttribute('unknown:name', 'value');
expect(div.hasAttribute('unknown:name')).toBe(true);
renderer.removeAttribute(div, 'name', 'unknown');
expect(div.hasAttribute('unknown:name')).toBe(false);
});
function shouldRemoveAttributeWithNs(namespace: string): void { function shouldRemoveAttributeWithNs(namespace: string): void {
const namespaceUri = NAMESPACE_URIS[namespace] || namespace; const namespaceUri = NAMESPACE_URIS[namespace];
const div = document.createElement('div'); const div = document.createElement('div');
div.setAttributeNS(namespaceUri, 'name', 'value'); div.setAttributeNS(namespaceUri, `${namespace}:name`, 'value');
expect(div.hasAttributeNS(namespaceUri, 'name')).toBe(true); expect(div.hasAttributeNS(namespaceUri, 'name')).toBe(true);
renderer.removeAttribute(div, 'name', namespace); renderer.removeAttribute(div, 'name', namespace);