Skip to content

Commit

Permalink
fixup! feat(ivy): provide sanitization methods which can be tree shaken
Browse files Browse the repository at this point in the history
  • Loading branch information
mhevery committed Mar 6, 2018
1 parent 87b7ac5 commit dee3447
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 20 deletions.
34 changes: 18 additions & 16 deletions packages/core/src/render3/instructions.ts
Expand Up @@ -39,10 +39,9 @@ export const NG_HOST_SYMBOL = '__ngHostLNode__';
const _CLEAN_PROMISE = Promise.resolve(null);

/**
* Function used to stringify the value before writing it into the renderer.
* Also used for sanitization.
* Function used to sanitize the value before writing it into the renderer.
*/
export type Stringifier = (value: any) => string;
export type Sanitizer = (value: any) => string;


/**
Expand Down Expand Up @@ -694,18 +693,17 @@ export function elementEnd() {
* @param name name The name of the attribute.
* @param value value The attribute is removed when value is `null` or `undefined`.
* Otherwise the attribute value is set to the stringified value.
* @param stringifier An optional function used to transform the value typically used for
* sanitization.
* @param sanitizer An optional function used to sanitize the value.
*/
export function elementAttribute(
index: number, name: string, value: any, stringifier?: Stringifier): void {
index: number, name: string, value: any, sanitizer?: Sanitizer): void {
if (value !== NO_CHANGE) {
const element: LElementNode = data[index];
if (value == null) {
isProceduralRenderer(renderer) ? renderer.removeAttribute(element.native, name) :
element.native.removeAttribute(name);
} else {
const strValue = stringifier == null ? stringify(value) : stringifier(value);
const strValue = sanitizer == null ? stringify(value) : sanitizer(value);
isProceduralRenderer(renderer) ? renderer.setAttribute(element.native, name, strValue) :
element.native.setAttribute(name, strValue);
}
Expand All @@ -723,12 +721,11 @@ export function elementAttribute(
* @param propName Name of property. Because it is going to DOM, this is not subject to
* renaming as part of minification.
* @param value New value to write.
* @param stringifier An optional function used to transform the value typically used for
* sanitization.
* @param sanitizer An optional function used to sanitize the value.
*/

export function elementProperty<T>(
index: number, propName: string, value: T | NO_CHANGE, stringifier?: Stringifier): void {
index: number, propName: string, value: T | NO_CHANGE, sanitizer?: Sanitizer): void {
if (value === NO_CHANGE) return;
const node = data[index] as LElementNode;
const tNode = node.tNode !;
Expand All @@ -745,7 +742,7 @@ export function elementProperty<T>(
setInputsForProperty(dataValue, value);
markDirtyIfOnPush(node);
} else {
value = (stringifier != null ? stringifier(value) : stringify(value)) as any;
value = (sanitizer != null ? sanitizer(value) : stringify(value)) as any;
const native = node.native;
isProceduralRenderer(renderer) ? renderer.setProperty(native, propName, value) :
(native.setProperty ? native.setProperty(propName, value) :
Expand Down Expand Up @@ -852,21 +849,26 @@ export function elementClass<T>(index: number, className: string, value: T | NO_
* renaming as part of minification.
* @param value New value to write (null to remove).
* @param suffix Optional suffix. Used with scalar values to add unit such as `px`.
* @param stringifier An optional function used to transform the value typically used for
* @param sanitizer An optional function used to transform the value typically used for
* sanitization.
*/
export function elementStyle<T>(
index: number, styleName: string, value: T | NO_CHANGE, suffix?: string | null,
stringifier?: Stringifier): void {
index: number, styleName: string, value: T | NO_CHANGE, suffix?: string): void;
export function elementStyle<T>(
index: number, styleName: string, value: T | NO_CHANGE, sanitizer?: Sanitizer): void;
export function elementStyle<T>(
index: number, styleName: string, value: T | NO_CHANGE,
suffixOrSanitizer?: string | Sanitizer): void {
if (value !== NO_CHANGE) {
const lElement = data[index] as LElementNode;
if (value == null) {
isProceduralRenderer(renderer) ?
renderer.removeStyle(lElement.native, styleName, RendererStyleFlags3.DashCase) :
lElement.native.style.removeProperty(styleName);
} else {
let strValue = stringifier == null ? stringify(value) : stringifier(value);
if (suffix) strValue = strValue + (stringifier == null ? suffix : stringifier(suffix));
let strValue =
typeof suffixOrSanitizer == 'function' ? suffixOrSanitizer(value) : stringify(value);
if (typeof suffixOrSanitizer == 'string') strValue = strValue + suffixOrSanitizer;
isProceduralRenderer(renderer) ?
renderer.setStyle(lElement.native, styleName, strValue, RendererStyleFlags3.DashCase) :
lElement.native.style.setProperty(styleName, strValue);
Expand Down
Expand Up @@ -47,7 +47,7 @@ describe('compiler sanitization', () => {
$r3$.ɵe();
}
$r3$.ɵp(0, 'innerHTML', $r3$.ɵb(ctx.innerHTML), $r3$.ɵsanitizeHtml);
$r3$.ɵs(1, 'background-image', $r3$.ɵb(ctx.style), null, $r3$.ɵsanitizeStyle);
$r3$.ɵs(1, 'background-image', $r3$.ɵb(ctx.style), $r3$.ɵsanitizeStyle);
$r3$.ɵp(1, 'src', $r3$.ɵb(ctx.url), $r3$.ɵsanitizeUrl);
$r3$.ɵa(1, 'srcset', $r3$.ɵb(ctx.url), $r3$.ɵsanitizeUrl);
}
Expand Down
5 changes: 2 additions & 3 deletions packages/core/test/render3/instructions_spec.ts
Expand Up @@ -50,14 +50,13 @@ describe('instructions', () => {
describe('elementStyle', () => {
it('should use sanitizer function', () => {
const t = new TemplateFixture(createDiv);
t.update(
() => elementStyle(0, 'background-image', 'url("http://server")', null, sanitizeStyle));
t.update(() => elementStyle(0, 'background-image', 'url("http://server")', sanitizeStyle));
// nothing is set because sanitizer suppresses it.
expect(t.html).toEqual('<div></div>');

t.update(
() => elementStyle(
0, 'background-image', bypassSanitizationTrustStyle('url("http://server")'), null,
0, 'background-image', bypassSanitizationTrustStyle('url("http://server")'),
sanitizeStyle));
expect((t.hostElement.firstChild as HTMLElement).style.getPropertyValue('background-image'))
.toEqual('url("http://server")');
Expand Down

0 comments on commit dee3447

Please sign in to comment.