fix(core): support sanitizer value in the [style] bindings (#35564)
When binding to `[style]` we correctly sanitized/unwrapped properties but we did not do it for the object itself. ``` @HostBinding("style") style: SafeStyle = this.sanitizer.bypassSecurityTrustStyle( "background: red; color: white; display: block;" ); ``` Above code would fail since the `[style]` would not unwrap the `SafeValue` and would treat it as object resulting in incorrect behavior. Fix #35476 (FW-1875) PR Close #35564
This commit is contained in:
parent
975a11b37f
commit
3af103aa61
|
@ -625,23 +625,25 @@ export function getHostDirectiveDef(tData: TData): DirectiveDef<any>|null {
|
||||||
export function toStylingKeyValueArray(
|
export function toStylingKeyValueArray(
|
||||||
keyValueArraySet: (keyValueArray: KeyValueArray<any>, key: string, value: any) => void,
|
keyValueArraySet: (keyValueArray: KeyValueArray<any>, key: string, value: any) => void,
|
||||||
stringParser: (styleKeyValueArray: KeyValueArray<any>, text: string) => void,
|
stringParser: (styleKeyValueArray: KeyValueArray<any>, text: string) => void,
|
||||||
value: string|string[]|{[key: string]: any}|null|undefined): KeyValueArray<any> {
|
value: string|string[]|{[key: string]: any}|SafeValue|null|undefined): KeyValueArray<any> {
|
||||||
if (value == null /*|| value === undefined */ || value === '') return EMPTY_ARRAY as any;
|
if (value == null /*|| value === undefined */ || value === '') return EMPTY_ARRAY as any;
|
||||||
const styleKeyValueArray: KeyValueArray<any> = [] as any;
|
const styleKeyValueArray: KeyValueArray<any> = [] as any;
|
||||||
if (Array.isArray(value)) {
|
const unwrappedValue = unwrapSafeValue(value) as string | string[] | {[key: string]: any};
|
||||||
for (let i = 0; i < value.length; i++) {
|
if (Array.isArray(unwrappedValue)) {
|
||||||
keyValueArraySet(styleKeyValueArray, value[i], true);
|
for (let i = 0; i < unwrappedValue.length; i++) {
|
||||||
|
keyValueArraySet(styleKeyValueArray, unwrappedValue[i], true);
|
||||||
}
|
}
|
||||||
} else if (typeof value === 'object') {
|
} else if (typeof unwrappedValue === 'object') {
|
||||||
for (const key in value) {
|
for (const key in unwrappedValue) {
|
||||||
if (value.hasOwnProperty(key)) {
|
if (unwrappedValue.hasOwnProperty(key)) {
|
||||||
keyValueArraySet(styleKeyValueArray, key, value[key]);
|
keyValueArraySet(styleKeyValueArray, key, unwrappedValue[key]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (typeof value === 'string') {
|
} else if (typeof unwrappedValue === 'string') {
|
||||||
stringParser(styleKeyValueArray, value);
|
stringParser(styleKeyValueArray, unwrappedValue);
|
||||||
} else {
|
} else {
|
||||||
ngDevMode && throwError('Unsupported styling type ' + typeof value + ': ' + value);
|
ngDevMode &&
|
||||||
|
throwError('Unsupported styling type ' + typeof unwrappedValue + ': ' + unwrappedValue);
|
||||||
}
|
}
|
||||||
return styleKeyValueArray;
|
return styleKeyValueArray;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3384,6 +3384,55 @@ describe('styling', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('regression', () => {
|
describe('regression', () => {
|
||||||
|
it('should support sanitizer value in the [style] bindings', () => {
|
||||||
|
if (!ivyEnabled && !supportsWritingStringsToStyleProperty()) {
|
||||||
|
// VE does not treat `[style]` as anything special, instead it simply writes to the
|
||||||
|
// `style` property on the element like so `element.style=value`. This seems to work fine
|
||||||
|
// every where except ie10, where it throws an error and as a consequence this test fails in
|
||||||
|
// VE on ie10.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
@Component({template: `<div [style]="style"></div>`})
|
||||||
|
class HostBindingTestComponent {
|
||||||
|
style: SafeStyle = this.sanitizer.bypassSecurityTrustStyle('color: white; display: block;');
|
||||||
|
constructor(private sanitizer: DomSanitizer) {}
|
||||||
|
}
|
||||||
|
TestBed.configureTestingModule({declarations: [HostBindingTestComponent]});
|
||||||
|
const fixture = TestBed.createComponent(HostBindingTestComponent);
|
||||||
|
fixture.detectChanges();
|
||||||
|
const div: HTMLElement = fixture.nativeElement.querySelector('div');
|
||||||
|
expectStyle(div).toEqual({color: 'white', display: 'block'});
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests to see if the current browser supports non standard way of writing into styles.
|
||||||
|
*
|
||||||
|
* This is not the correct way to write to style and is not supported in ie10.
|
||||||
|
* ```
|
||||||
|
* div.style = 'color: white';
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* This is the correct way to write to styles:
|
||||||
|
* ```
|
||||||
|
* div.style.cssText = 'color: white';
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Even though writing to `div.style` is not officially supported, it works in all
|
||||||
|
* browsers except ie10.
|
||||||
|
*
|
||||||
|
* This function detects this condition and allows us to skip the test.
|
||||||
|
*/
|
||||||
|
function supportsWritingStringsToStyleProperty() {
|
||||||
|
const div = document.createElement('div');
|
||||||
|
const CSS = 'color: white;';
|
||||||
|
try {
|
||||||
|
(div as any).style = CSS;
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return div.style.cssText === CSS;
|
||||||
|
}
|
||||||
|
|
||||||
onlyInIvy('styling priority resolution is Ivy only feature.')
|
onlyInIvy('styling priority resolution is Ivy only feature.')
|
||||||
.it('should allow lookahead binding on second pass #35118', () => {
|
.it('should allow lookahead binding on second pass #35118', () => {
|
||||||
@Component({
|
@Component({
|
||||||
|
@ -3445,4 +3494,4 @@ function expectStyle(element: HTMLElement) {
|
||||||
|
|
||||||
function expectClass(element: HTMLElement) {
|
function expectClass(element: HTMLElement) {
|
||||||
return expect(getElementClasses(element));
|
return expect(getElementClasses(element));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue