fix(ivy): elements properties should not be stringified (#22683)
PR Close #22683
This commit is contained in:
parent
cd58c0a6d9
commit
f95730b8e2
|
@ -755,7 +755,9 @@ export function elementProperty<T>(
|
||||||
setInputsForProperty(dataValue, value);
|
setInputsForProperty(dataValue, value);
|
||||||
markDirtyIfOnPush(node);
|
markDirtyIfOnPush(node);
|
||||||
} else {
|
} else {
|
||||||
value = (sanitizer != null ? sanitizer(value) : stringify(value)) as any;
|
// It is assumed that the sanitizer is only added when the compiler determines that the property
|
||||||
|
// is risky, so sanitization can be done without further checks.
|
||||||
|
value = sanitizer != null ? (sanitizer(value) as any) : value;
|
||||||
const native = node.native;
|
const native = node.native;
|
||||||
isProceduralRenderer(renderer) ? renderer.setProperty(native, propName, value) :
|
isProceduralRenderer(renderer) ? renderer.setProperty(native, propName, value) :
|
||||||
(native.setProperty ? native.setProperty(propName, value) :
|
(native.setProperty ? native.setProperty(propName, value) :
|
||||||
|
|
|
@ -25,12 +25,13 @@ describe('compiler sanitization', () => {
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'my-component',
|
selector: 'my-component',
|
||||||
template: `<div [innerHTML]="innerHTML"></div>` +
|
template: `<div [innerHTML]="innerHTML" [hidden]="hidden"></div>` +
|
||||||
`<img [style.background-image]="style" [src]="src">` +
|
`<img [style.background-image]="style" [src]="src">` +
|
||||||
`<script [attr.src]=src></script>`
|
`<script [attr.src]=src></script>`
|
||||||
})
|
})
|
||||||
class MyComponent {
|
class MyComponent {
|
||||||
innerHTML: string = '<frame></frame>';
|
innerHTML: string = '<frame></frame>';
|
||||||
|
hidden: boolean = true;
|
||||||
style: string = `url("http://evil")`;
|
style: string = `url("http://evil")`;
|
||||||
url: string = 'javascript:evil()';
|
url: string = 'javascript:evil()';
|
||||||
|
|
||||||
|
@ -47,6 +48,7 @@ describe('compiler sanitization', () => {
|
||||||
$r3$.ɵe();
|
$r3$.ɵe();
|
||||||
}
|
}
|
||||||
$r3$.ɵp(0, 'innerHTML', $r3$.ɵb(ctx.innerHTML), $r3$.ɵsanitizeHtml);
|
$r3$.ɵp(0, 'innerHTML', $r3$.ɵb(ctx.innerHTML), $r3$.ɵsanitizeHtml);
|
||||||
|
$r3$.ɵp(0, 'hidden', $r3$.ɵb(ctx.hidden));
|
||||||
$r3$.ɵs(1, 'background-image', $r3$.ɵb(ctx.style), $r3$.ɵsanitizeStyle);
|
$r3$.ɵs(1, 'background-image', $r3$.ɵb(ctx.style), $r3$.ɵsanitizeStyle);
|
||||||
$r3$.ɵp(1, 'src', $r3$.ɵb(ctx.url), $r3$.ɵsanitizeUrl);
|
$r3$.ɵp(1, 'src', $r3$.ɵb(ctx.url), $r3$.ɵsanitizeUrl);
|
||||||
$r3$.ɵa(1, 'srcset', $r3$.ɵb(ctx.url), $r3$.ɵsanitizeUrl);
|
$r3$.ɵa(1, 'srcset', $r3$.ɵb(ctx.url), $r3$.ɵsanitizeUrl);
|
||||||
|
@ -59,6 +61,7 @@ describe('compiler sanitization', () => {
|
||||||
const div = getHostElement(myComponent).querySelector('div') !;
|
const div = getHostElement(myComponent).querySelector('div') !;
|
||||||
// because sanitizer removed it is working.
|
// because sanitizer removed it is working.
|
||||||
expect(div.innerHTML).toEqual('');
|
expect(div.innerHTML).toEqual('');
|
||||||
|
expect(div.hidden).toEqual(true);
|
||||||
|
|
||||||
const img = getHostElement(myComponent).querySelector('img') !;
|
const img = getHostElement(myComponent).querySelector('img') !;
|
||||||
// because sanitizer removed it is working.
|
// because sanitizer removed it is working.
|
||||||
|
|
|
@ -34,7 +34,7 @@ describe('instructions', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('elementProperty', () => {
|
describe('elementProperty', () => {
|
||||||
it('should use sanitizer function', () => {
|
it('should use sanitizer function when available', () => {
|
||||||
const t = new TemplateFixture(createDiv);
|
const t = new TemplateFixture(createDiv);
|
||||||
|
|
||||||
t.update(() => elementProperty(0, 'title', 'javascript:true', sanitizeUrl));
|
t.update(() => elementProperty(0, 'title', 'javascript:true', sanitizeUrl));
|
||||||
|
@ -45,6 +45,14 @@ describe('instructions', () => {
|
||||||
0, 'title', bypassSanitizationTrustUrl('javascript:false'), sanitizeUrl));
|
0, 'title', bypassSanitizationTrustUrl('javascript:false'), sanitizeUrl));
|
||||||
expect(t.html).toEqual('<div title="javascript:false"></div>');
|
expect(t.html).toEqual('<div title="javascript:false"></div>');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should not stringify non string values', () => {
|
||||||
|
const t = new TemplateFixture(createDiv);
|
||||||
|
|
||||||
|
t.update(() => elementProperty(0, 'hidden', false));
|
||||||
|
// The hidden property would be true if `false` was stringified into `"false"`.
|
||||||
|
expect((t.hostNode.native as HTMLElement).querySelector('div') !.hidden).toEqual(false);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('elementStyle', () => {
|
describe('elementStyle', () => {
|
||||||
|
|
Loading…
Reference in New Issue