Skip to content
Permalink
Browse files

fix(ivy): handle SafeStyles in [style.prop] correctly (#34286)

Prior to this commit, values wrapped into SafeStyle were not handled correctly in [style.prop] bindings in case style sanitizer is present (when template contains some style props that require sanitization). Style sanitizer was not unwrapping values in case a given prop doesn't require sanitization.As a result, wrapped values were used as final styling values (see https://github.com/angular/angular/blob/master/packages/core/src/render3/styling/bindings.ts#L620). This commit updates the logic to unwrap safe values in sanitizer in case no sanitization is required.

PR Close #34286
  • Loading branch information
AndrewKushnir committed Dec 6, 2019
1 parent 7c2bb37 commit b0d5784b63a2b73bcf2aa55c1587ed8189736f3a
Showing with 60 additions and 1 deletion.
  1. +1 −1 packages/core/src/sanitization/sanitization.ts
  2. +59 −0 packages/core/test/acceptance/styling_spec.ts
@@ -196,7 +196,7 @@ export const ɵɵdefaultStyleSanitizer =
}

if (mode & StyleSanitizeMode.SanitizeOnly) {
return doSanitizeValue ? ɵɵsanitizeStyle(value) : value;
return doSanitizeValue ? ɵɵsanitizeStyle(value) : unwrapSafeValue(value);
} else {
return doSanitizeValue;
}
@@ -5,6 +5,7 @@
* 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
*/
import {CommonModule} from '@angular/common';
import {Component, ComponentFactoryResolver, ComponentRef, Directive, ElementRef, HostBinding, Input, NgModule, Renderer2, ViewChild, ViewContainerRef} from '@angular/core';
import {getDebugNode} from '@angular/core/src/render3/util/discovery_utils';
import {ngDevModeResetPerfCounters} from '@angular/core/src/util/ng_dev_mode';
@@ -1563,6 +1564,64 @@ describe('styling', () => {
expect(html).toMatch(/style=["|']clip-path:\s*url\(.*#test.*\)/);
});

it('should handle values wrapped into SafeValue', () => {
@Component({
template: `
<!-- Verify sanitizable style prop values wrapped in SafeValue -->
<div [style.background]="getBackgroundSafe()"></div>
<!-- Verify regular style prop values wrapped in SafeValue -->
<p [style.width]="getWidthSafe()" [style.height]="getHeightSafe()"></p>
<!-- Verify regular style prop values not wrapped in SafeValue -->
<span [style.color]="getColorUnsafe()"></span>
`,
})
class MyComp {
constructor(private sanitizer: DomSanitizer) {}
public width: string = 'calc(20%)';
public height: string = '10px';
public background: string = '1.png';
public color: string = 'red';

private getSafeStyle(value: string) { return this.sanitizer.bypassSecurityTrustStyle(value); }

getBackgroundSafe() { return this.getSafeStyle(`url("/${this.background}")`); }
getWidthSafe() { return this.getSafeStyle(this.width); }
getHeightSafe() { return this.getSafeStyle(this.height); }
getColorUnsafe() { return this.color; }
}

TestBed.configureTestingModule({
imports: [CommonModule],
declarations: [MyComp],
});
const fixture = TestBed.createComponent(MyComp);
fixture.detectChanges();

const comp = fixture.componentInstance;
const div = fixture.nativeElement.querySelector('div');
const p = fixture.nativeElement.querySelector('p');
const span = fixture.nativeElement.querySelector('span');

expect(div.style.background).toContain('url("/1.png")');
expect(p.style.width).toBe('calc(20%)');
expect(p.style.height).toBe('10px');
expect(span.style.color).toBe('red');

comp.background = '2.png';
comp.width = '5px';
comp.height = '100%';
comp.color = 'green';

fixture.detectChanges();

expect(div.style.background).toContain('url("/2.png")');
expect(p.style.width).toBe('5px');
expect(p.style.height).toBe('100%');
expect(span.style.color).toBe('green');
});

onlyInIvy('only ivy has style/class bindings debugging support')
.it('should evaluate follow-up [style] maps even if a former map is null', () => {
@Directive({selector: '[dir-with-styling]'})

0 comments on commit b0d5784

Please sign in to comment.
You can’t perform that action at this time.