revert: refactor(ivy): remove styleSanitizer instruction in favor of an inline param (#34480) (#34910)
This reverts commit 84d24c08e1
.
PR Close #34910
This commit is contained in:
parent
61ad50d40a
commit
32489c7426
|
@ -377,6 +377,7 @@ describe('compiler compliance: styling', () => {
|
||||||
$r3$.ɵɵelement(0, "div");
|
$r3$.ɵɵelement(0, "div");
|
||||||
}
|
}
|
||||||
if (rf & 2) {
|
if (rf & 2) {
|
||||||
|
$r3$.ɵɵstyleSanitizer($r3$.ɵɵdefaultStyleSanitizer);
|
||||||
$r3$.ɵɵstyleMap($ctx$.myStyleExp);
|
$r3$.ɵɵstyleMap($ctx$.myStyleExp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -510,6 +511,7 @@ describe('compiler compliance: styling', () => {
|
||||||
$r3$.ɵɵelement(0, "div", 0);
|
$r3$.ɵɵelement(0, "div", 0);
|
||||||
}
|
}
|
||||||
if (rf & 2) {
|
if (rf & 2) {
|
||||||
|
$r3$.ɵɵstyleSanitizer($r3$.ɵɵdefaultStyleSanitizer);
|
||||||
$r3$.ɵɵstyleMap($ctx$.myStyleExp);
|
$r3$.ɵɵstyleMap($ctx$.myStyleExp);
|
||||||
$r3$.ɵɵstyleProp("width", $ctx$.myWidth)("height", $ctx$.myHeight);
|
$r3$.ɵɵstyleProp("width", $ctx$.myWidth)("height", $ctx$.myHeight);
|
||||||
$r3$.ɵɵattribute("style", "border-width: 10px", $r3$.ɵɵsanitizeStyle);
|
$r3$.ɵɵattribute("style", "border-width: 10px", $r3$.ɵɵsanitizeStyle);
|
||||||
|
@ -555,7 +557,8 @@ describe('compiler compliance: styling', () => {
|
||||||
$r3$.ɵɵelement(0, "div");
|
$r3$.ɵɵelement(0, "div");
|
||||||
}
|
}
|
||||||
if (rf & 2) {
|
if (rf & 2) {
|
||||||
$r3$.ɵɵstyleProp("background-image", ctx.myImage, $r3$.ɵɵdefaultStyleSanitizer);
|
$r3$.ɵɵstyleSanitizer($r3$.ɵɵdefaultStyleSanitizer);
|
||||||
|
$r3$.ɵɵstyleProp("background-image", ctx.myImage);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
encapsulation: 2
|
encapsulation: 2
|
||||||
|
@ -813,6 +816,7 @@ describe('compiler compliance: styling', () => {
|
||||||
$r3$.ɵɵelement(0, "div");
|
$r3$.ɵɵelement(0, "div");
|
||||||
}
|
}
|
||||||
if (rf & 2) {
|
if (rf & 2) {
|
||||||
|
$r3$.ɵɵstyleSanitizer($r3$.ɵɵdefaultStyleSanitizer);
|
||||||
$r3$.ɵɵstyleMap($ctx$.myStyleExp);
|
$r3$.ɵɵstyleMap($ctx$.myStyleExp);
|
||||||
$r3$.ɵɵclassMap($ctx$.myClassExp);
|
$r3$.ɵɵclassMap($ctx$.myClassExp);
|
||||||
}
|
}
|
||||||
|
@ -854,6 +858,7 @@ describe('compiler compliance: styling', () => {
|
||||||
$r3$.ɵɵelementEnd();
|
$r3$.ɵɵelementEnd();
|
||||||
}
|
}
|
||||||
if (rf & 2) {
|
if (rf & 2) {
|
||||||
|
$r3$.ɵɵstyleSanitizer($r3$.ɵɵdefaultStyleSanitizer);
|
||||||
$r3$.ɵɵstyleMap($r3$.ɵɵpipeBind1(1, 4, $ctx$.myStyleExp));
|
$r3$.ɵɵstyleMap($r3$.ɵɵpipeBind1(1, 4, $ctx$.myStyleExp));
|
||||||
$r3$.ɵɵclassMap($r3$.ɵɵpipeBind1(2, 6, $ctx$.myClassExp));
|
$r3$.ɵɵclassMap($r3$.ɵɵpipeBind1(2, 6, $ctx$.myClassExp));
|
||||||
}
|
}
|
||||||
|
@ -906,6 +911,7 @@ describe('compiler compliance: styling', () => {
|
||||||
$r3$.ɵɵelementEnd();
|
$r3$.ɵɵelementEnd();
|
||||||
}
|
}
|
||||||
if (rf & 2) {
|
if (rf & 2) {
|
||||||
|
$r3$.ɵɵstyleSanitizer($r3$.ɵɵdefaultStyleSanitizer);
|
||||||
$r3$.ɵɵstyleMap($r3$.ɵɵpipeBind2(1, 8, $ctx$.myStyleExp, 1000));
|
$r3$.ɵɵstyleMap($r3$.ɵɵpipeBind2(1, 8, $ctx$.myStyleExp, 1000));
|
||||||
$r3$.ɵɵclassMap($r3$.ɵɵpureFunction0(20, _c0));
|
$r3$.ɵɵclassMap($r3$.ɵɵpureFunction0(20, _c0));
|
||||||
$r3$.ɵɵstyleProp("bar", $r3$.ɵɵpipeBind2(2, 11, $ctx$.barExp, 3000))("baz", $r3$.ɵɵpipeBind2(3, 14, $ctx$.bazExp, 4000));
|
$r3$.ɵɵstyleProp("bar", $r3$.ɵɵpipeBind2(2, 11, $ctx$.barExp, 3000))("baz", $r3$.ɵɵpipeBind2(3, 14, $ctx$.bazExp, 4000));
|
||||||
|
@ -1011,6 +1017,7 @@ describe('compiler compliance: styling', () => {
|
||||||
$r3$.ɵɵelementHostAttrs($e0_attrs$);
|
$r3$.ɵɵelementHostAttrs($e0_attrs$);
|
||||||
}
|
}
|
||||||
if (rf & 2) {
|
if (rf & 2) {
|
||||||
|
$r3$.ɵɵstyleSanitizer($r3$.ɵɵdefaultStyleSanitizer);
|
||||||
$r3$.ɵɵstyleMap(ctx.myStyle);
|
$r3$.ɵɵstyleMap(ctx.myStyle);
|
||||||
$r3$.ɵɵclassMap(ctx.myClass);
|
$r3$.ɵɵclassMap(ctx.myClass);
|
||||||
$r3$.ɵɵstyleProp("color", ctx.myColorProp);
|
$r3$.ɵɵstyleProp("color", ctx.myColorProp);
|
||||||
|
@ -1068,6 +1075,7 @@ describe('compiler compliance: styling', () => {
|
||||||
$r3$.ɵɵallocHostVars(8);
|
$r3$.ɵɵallocHostVars(8);
|
||||||
}
|
}
|
||||||
if (rf & 2) {
|
if (rf & 2) {
|
||||||
|
$r3$.ɵɵstyleSanitizer($r3$.ɵɵdefaultStyleSanitizer);
|
||||||
$r3$.ɵɵstyleMap(ctx.myStyle);
|
$r3$.ɵɵstyleMap(ctx.myStyle);
|
||||||
$r3$.ɵɵclassMap(ctx.myClasses);
|
$r3$.ɵɵclassMap(ctx.myClasses);
|
||||||
$r3$.ɵɵstyleProp("height", ctx.myHeightProp, "pt")("width", ctx.myWidthProp);
|
$r3$.ɵɵstyleProp("height", ctx.myHeightProp, "pt")("width", ctx.myWidthProp);
|
||||||
|
@ -1125,6 +1133,7 @@ describe('compiler compliance: styling', () => {
|
||||||
$r3$.ɵɵelement(0, "div");
|
$r3$.ɵɵelement(0, "div");
|
||||||
}
|
}
|
||||||
if (rf & 2) {
|
if (rf & 2) {
|
||||||
|
$r3$.ɵɵstyleSanitizer($r3$.ɵɵdefaultStyleSanitizer);
|
||||||
$r3$.ɵɵstyleMap(ctx.myStyleExp);
|
$r3$.ɵɵstyleMap(ctx.myStyleExp);
|
||||||
$r3$.ɵɵclassMap(ctx.myClassExp);
|
$r3$.ɵɵclassMap(ctx.myClassExp);
|
||||||
$r3$.ɵɵstyleProp("height", ctx.myHeightExp);
|
$r3$.ɵɵstyleProp("height", ctx.myHeightExp);
|
||||||
|
@ -1139,6 +1148,7 @@ describe('compiler compliance: styling', () => {
|
||||||
$r3$.ɵɵallocHostVars(6);
|
$r3$.ɵɵallocHostVars(6);
|
||||||
}
|
}
|
||||||
if (rf & 2) {
|
if (rf & 2) {
|
||||||
|
$r3$.ɵɵstyleSanitizer($r3$.ɵɵdefaultStyleSanitizer);
|
||||||
$r3$.ɵɵstyleMap(ctx.myStyleExp);
|
$r3$.ɵɵstyleMap(ctx.myStyleExp);
|
||||||
$r3$.ɵɵclassMap(ctx.myClassExp);
|
$r3$.ɵɵclassMap(ctx.myClassExp);
|
||||||
$r3$.ɵɵstyleProp("width", ctx.myWidthExp);
|
$r3$.ɵɵstyleProp("width", ctx.myWidthExp);
|
||||||
|
@ -1414,46 +1424,6 @@ describe('compiler compliance: styling', () => {
|
||||||
expectEmit(result.source, template, 'Incorrect handling of interpolated style properties');
|
expectEmit(result.source, template, 'Incorrect handling of interpolated style properties');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should generate update instructions for interpolated style properties with a sanitizer',
|
|
||||||
() => {
|
|
||||||
const files = {
|
|
||||||
app: {
|
|
||||||
'spec.ts': `
|
|
||||||
import {Component} from '@angular/core';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
template: \`
|
|
||||||
<div style.background="url({{ myUrl1 }})"
|
|
||||||
style.borderImage="url({{ myUrl2 }}) {{ myRepeat }} auto"
|
|
||||||
style.boxShadow="{{ myBoxX }} {{ myBoxY }} {{ myBoxWidth }} black"></div>
|
|
||||||
\`
|
|
||||||
})
|
|
||||||
export class MyComponent {
|
|
||||||
myUrl1 = '...';
|
|
||||||
myUrl2 = '...';
|
|
||||||
myBoxX = '0px';
|
|
||||||
myBoxY = '0px';
|
|
||||||
myBoxWidth = '100px';
|
|
||||||
myRepeat = 'no-repeat';
|
|
||||||
}
|
|
||||||
`
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const template = `
|
|
||||||
…
|
|
||||||
if (rf & 2) {
|
|
||||||
$r3$.ɵɵstylePropInterpolate1("background", "url(", ctx.myUrl1, ")", $r3$.ɵɵdefaultStyleSanitizer);
|
|
||||||
$r3$.ɵɵstylePropInterpolate2("border-image", "url(", ctx.myUrl2, ") ", ctx.myRepeat, " auto", $r3$.ɵɵdefaultStyleSanitizer);
|
|
||||||
$r3$.ɵɵstylePropInterpolate3("box-shadow", "", ctx.myBoxX, " ", ctx.myBoxY, " ", ctx.myBoxWidth, " black");
|
|
||||||
}
|
|
||||||
…
|
|
||||||
`;
|
|
||||||
const result = compile(files, angularFiles);
|
|
||||||
|
|
||||||
expectEmit(result.source, template, 'Incorrect handling of interpolated style properties');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should generate update instructions for interpolated style properties with !important',
|
it('should generate update instructions for interpolated style properties with !important',
|
||||||
() => {
|
() => {
|
||||||
const files = {
|
const files = {
|
||||||
|
@ -1879,6 +1849,7 @@ describe('compiler compliance: styling', () => {
|
||||||
}
|
}
|
||||||
if (rf & 2) {
|
if (rf & 2) {
|
||||||
$r3$.ɵɵhostProperty("id", ctx.id)("title", ctx.title);
|
$r3$.ɵɵhostProperty("id", ctx.id)("title", ctx.title);
|
||||||
|
$r3$.ɵɵstyleSanitizer($r3$.ɵɵdefaultStyleSanitizer);
|
||||||
$r3$.ɵɵstyleMap(ctx.myStyle);
|
$r3$.ɵɵstyleMap(ctx.myStyle);
|
||||||
$r3$.ɵɵclassMap(ctx.myClass);
|
$r3$.ɵɵclassMap(ctx.myClass);
|
||||||
}
|
}
|
||||||
|
@ -1931,7 +1902,7 @@ describe('compiler compliance: styling', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('new styling refactor', () => {
|
describe('new styling refactor', () => {
|
||||||
it('should generate a sanitizer value into the instruction when one or more sanitizable style properties are statically detected',
|
it('should generate a `styleSanitizer` instruction when one or more sanitizable style properties are statically detected',
|
||||||
() => {
|
() => {
|
||||||
const files = {
|
const files = {
|
||||||
app: {
|
app: {
|
||||||
|
@ -1955,7 +1926,8 @@ describe('compiler compliance: styling', () => {
|
||||||
template: function MyAppComp_Template(rf, ctx) {
|
template: function MyAppComp_Template(rf, ctx) {
|
||||||
…
|
…
|
||||||
if (rf & 2) {
|
if (rf & 2) {
|
||||||
$r3$.ɵɵstyleProp("background-image", ctx.bgExp, $r3$.ɵɵdefaultStyleSanitizer);
|
$r3$.ɵɵstyleSanitizer($r3$.ɵɵdefaultStyleSanitizer);
|
||||||
|
$r3$.ɵɵstyleProp("background-image", ctx.bgExp);
|
||||||
}
|
}
|
||||||
…
|
…
|
||||||
}
|
}
|
||||||
|
@ -1965,10 +1937,11 @@ describe('compiler compliance: styling', () => {
|
||||||
expectEmit(result.source, template, 'Incorrect template');
|
expectEmit(result.source, template, 'Incorrect template');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not add a sanitizer param when a `styleMap` instruction is used', () => {
|
it('should generate a `styleSanitizer` instruction when a `styleMap` instruction is used',
|
||||||
const files = {
|
() => {
|
||||||
app: {
|
const files = {
|
||||||
'spec.ts': `
|
app: {
|
||||||
|
'spec.ts': `
|
||||||
import {Component, NgModule} from '@angular/core';
|
import {Component, NgModule} from '@angular/core';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
@ -1981,24 +1954,25 @@ describe('compiler compliance: styling', () => {
|
||||||
mapExp = {};
|
mapExp = {};
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const template = `
|
const template = `
|
||||||
template: function MyAppComp_Template(rf, ctx) {
|
template: function MyAppComp_Template(rf, ctx) {
|
||||||
…
|
…
|
||||||
if (rf & 2) {
|
if (rf & 2) {
|
||||||
|
$r3$.ɵɵstyleSanitizer($r3$.ɵɵdefaultStyleSanitizer);
|
||||||
$r3$.ɵɵstyleMap(ctx.mapExp);
|
$r3$.ɵɵstyleMap(ctx.mapExp);
|
||||||
}
|
}
|
||||||
…
|
…
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const result = compile(files, angularFiles);
|
const result = compile(files, angularFiles);
|
||||||
expectEmit(result.source, template, 'Incorrect template');
|
expectEmit(result.source, template, 'Incorrect template');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('shouldn\'t generate a sanitizer param into the styling instruction when class-based instructions are used',
|
it('shouldn\'t generate a `styleSanitizer` instruction when class-based instructions are used',
|
||||||
() => {
|
() => {
|
||||||
const files = {
|
const files = {
|
||||||
app: {
|
app: {
|
||||||
|
|
|
@ -113,6 +113,8 @@ export class Identifiers {
|
||||||
static stylePropInterpolateV:
|
static stylePropInterpolateV:
|
||||||
o.ExternalReference = {name: 'ɵɵstylePropInterpolateV', moduleName: CORE};
|
o.ExternalReference = {name: 'ɵɵstylePropInterpolateV', moduleName: CORE};
|
||||||
|
|
||||||
|
static styleSanitizer: o.ExternalReference = {name: 'ɵɵstyleSanitizer', moduleName: CORE};
|
||||||
|
|
||||||
static elementHostAttrs: o.ExternalReference = {name: 'ɵɵelementHostAttrs', moduleName: CORE};
|
static elementHostAttrs: o.ExternalReference = {name: 'ɵɵelementHostAttrs', moduleName: CORE};
|
||||||
|
|
||||||
static containerCreate: o.ExternalReference = {name: 'ɵɵcontainer', moduleName: CORE};
|
static containerCreate: o.ExternalReference = {name: 'ɵɵcontainer', moduleName: CORE};
|
||||||
|
|
|
@ -44,7 +44,6 @@ interface BoundStylingEntry {
|
||||||
name: string|null;
|
name: string|null;
|
||||||
unit: string|null;
|
unit: string|null;
|
||||||
sourceSpan: ParseSourceSpan;
|
sourceSpan: ParseSourceSpan;
|
||||||
sanitize: boolean;
|
|
||||||
value: AST;
|
value: AST;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,6 +116,10 @@ export class StylingBuilder {
|
||||||
private _initialStyleValues: string[] = [];
|
private _initialStyleValues: string[] = [];
|
||||||
private _initialClassValues: string[] = [];
|
private _initialClassValues: string[] = [];
|
||||||
|
|
||||||
|
// certain style properties ALWAYS need sanitization
|
||||||
|
// this is checked each time new styles are encountered
|
||||||
|
private _useDefaultSanitizer = false;
|
||||||
|
|
||||||
constructor(private _elementIndexExpr: o.Expression, private _directiveExpr: o.Expression|null) {}
|
constructor(private _elementIndexExpr: o.Expression, private _directiveExpr: o.Expression|null) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -176,13 +179,14 @@ export class StylingBuilder {
|
||||||
const {property, hasOverrideFlag, unit: bindingUnit} = parseProperty(name);
|
const {property, hasOverrideFlag, unit: bindingUnit} = parseProperty(name);
|
||||||
const entry: BoundStylingEntry = {
|
const entry: BoundStylingEntry = {
|
||||||
name: property,
|
name: property,
|
||||||
sanitize: property ? isStyleSanitizable(property) : true,
|
|
||||||
unit: unit || bindingUnit, value, sourceSpan, hasOverrideFlag
|
unit: unit || bindingUnit, value, sourceSpan, hasOverrideFlag
|
||||||
};
|
};
|
||||||
if (isMapBased) {
|
if (isMapBased) {
|
||||||
|
this._useDefaultSanitizer = true;
|
||||||
this._styleMapInput = entry;
|
this._styleMapInput = entry;
|
||||||
} else {
|
} else {
|
||||||
(this._singleStyleInputs = this._singleStyleInputs || []).push(entry);
|
(this._singleStyleInputs = this._singleStyleInputs || []).push(entry);
|
||||||
|
this._useDefaultSanitizer = this._useDefaultSanitizer || isStyleSanitizable(name);
|
||||||
registerIntoMap(this._stylesIndex, property);
|
registerIntoMap(this._stylesIndex, property);
|
||||||
}
|
}
|
||||||
this._lastStylingInput = entry;
|
this._lastStylingInput = entry;
|
||||||
|
@ -198,8 +202,8 @@ export class StylingBuilder {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const {property, hasOverrideFlag} = parseProperty(name);
|
const {property, hasOverrideFlag} = parseProperty(name);
|
||||||
const entry: BoundStylingEntry =
|
const entry:
|
||||||
{name: property, value, sourceSpan, sanitize: false, hasOverrideFlag, unit: null};
|
BoundStylingEntry = {name: property, value, sourceSpan, hasOverrideFlag, unit: null};
|
||||||
if (isMapBased) {
|
if (isMapBased) {
|
||||||
if (this._classMapInput) {
|
if (this._classMapInput) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
|
@ -360,9 +364,10 @@ export class StylingBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
private _buildSingleInputs(
|
private _buildSingleInputs(
|
||||||
reference: o.ExternalReference, inputs: BoundStylingEntry[], valueConverter: ValueConverter,
|
reference: o.ExternalReference, inputs: BoundStylingEntry[], mapIndex: Map<string, number>,
|
||||||
getInterpolationExpressionFn: ((value: Interpolation) => o.ExternalReference)|null,
|
allowUnits: boolean, valueConverter: ValueConverter,
|
||||||
isClassBased: boolean): StylingInstruction[] {
|
getInterpolationExpressionFn?: (value: Interpolation) => o.ExternalReference):
|
||||||
|
StylingInstruction[] {
|
||||||
const instructions: StylingInstruction[] = [];
|
const instructions: StylingInstruction[] = [];
|
||||||
|
|
||||||
inputs.forEach(input => {
|
inputs.forEach(input => {
|
||||||
|
@ -385,7 +390,7 @@ export class StylingBuilder {
|
||||||
allocateBindingSlots: totalBindingSlotsRequired,
|
allocateBindingSlots: totalBindingSlotsRequired,
|
||||||
supportsInterpolation: !!getInterpolationExpressionFn,
|
supportsInterpolation: !!getInterpolationExpressionFn,
|
||||||
params: (convertFn: (value: any) => o.Expression | o.Expression[]) => {
|
params: (convertFn: (value: any) => o.Expression | o.Expression[]) => {
|
||||||
// params => stylingProp(propName, value, suffix|sanitizer)
|
// params => stylingProp(propName, value)
|
||||||
const params: o.Expression[] = [];
|
const params: o.Expression[] = [];
|
||||||
params.push(o.literal(input.name));
|
params.push(o.literal(input.name));
|
||||||
|
|
||||||
|
@ -396,16 +401,8 @@ export class StylingBuilder {
|
||||||
params.push(convertResult);
|
params.push(convertResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
// [style.prop] bindings may use suffix values (e.g. px, em, etc...) and they
|
if (allowUnits && input.unit) {
|
||||||
// can also use a sanitizer. Sanitization occurs for url-based entries. Having
|
params.push(o.literal(input.unit));
|
||||||
// the suffix value and a sanitizer together into the instruction doesn't make
|
|
||||||
// any sense (url-based entries cannot be sanitized).
|
|
||||||
if (!isClassBased) {
|
|
||||||
if (input.unit) {
|
|
||||||
params.push(o.literal(input.unit));
|
|
||||||
} else if (input.sanitize) {
|
|
||||||
params.push(o.importExpr(R3.defaultStyleSanitizer));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return params;
|
return params;
|
||||||
|
@ -430,7 +427,7 @@ export class StylingBuilder {
|
||||||
private _buildClassInputs(valueConverter: ValueConverter): StylingInstruction[] {
|
private _buildClassInputs(valueConverter: ValueConverter): StylingInstruction[] {
|
||||||
if (this._singleClassInputs) {
|
if (this._singleClassInputs) {
|
||||||
return this._buildSingleInputs(
|
return this._buildSingleInputs(
|
||||||
R3.classProp, this._singleClassInputs, valueConverter, null, true);
|
R3.classProp, this._singleClassInputs, this._classesIndex, false, valueConverter);
|
||||||
}
|
}
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
@ -438,12 +435,23 @@ export class StylingBuilder {
|
||||||
private _buildStyleInputs(valueConverter: ValueConverter): StylingInstruction[] {
|
private _buildStyleInputs(valueConverter: ValueConverter): StylingInstruction[] {
|
||||||
if (this._singleStyleInputs) {
|
if (this._singleStyleInputs) {
|
||||||
return this._buildSingleInputs(
|
return this._buildSingleInputs(
|
||||||
R3.styleProp, this._singleStyleInputs, valueConverter,
|
R3.styleProp, this._singleStyleInputs, this._stylesIndex, true, valueConverter,
|
||||||
getStylePropInterpolationExpression, false);
|
getStylePropInterpolationExpression);
|
||||||
}
|
}
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _buildSanitizerFn(): StylingInstruction {
|
||||||
|
return {
|
||||||
|
reference: R3.styleSanitizer,
|
||||||
|
calls: [{
|
||||||
|
sourceSpan: this._firstStylingInput ? this._firstStylingInput.sourceSpan : null,
|
||||||
|
allocateBindingSlots: 0,
|
||||||
|
params: () => [o.importExpr(R3.defaultStyleSanitizer)]
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs all instructions which contain the expressions that will be placed
|
* Constructs all instructions which contain the expressions that will be placed
|
||||||
* into the update block of a template function or a directive hostBindings function.
|
* into the update block of a template function or a directive hostBindings function.
|
||||||
|
@ -451,6 +459,9 @@ export class StylingBuilder {
|
||||||
buildUpdateLevelInstructions(valueConverter: ValueConverter) {
|
buildUpdateLevelInstructions(valueConverter: ValueConverter) {
|
||||||
const instructions: StylingInstruction[] = [];
|
const instructions: StylingInstruction[] = [];
|
||||||
if (this.hasBindings) {
|
if (this.hasBindings) {
|
||||||
|
if (this._useDefaultSanitizer) {
|
||||||
|
instructions.push(this._buildSanitizerFn());
|
||||||
|
}
|
||||||
const styleMapInstruction = this.buildStyleMapInstruction(valueConverter);
|
const styleMapInstruction = this.buildStyleMapInstruction(valueConverter);
|
||||||
if (styleMapInstruction) {
|
if (styleMapInstruction) {
|
||||||
instructions.push(styleMapInstruction);
|
instructions.push(styleMapInstruction);
|
||||||
|
|
|
@ -122,6 +122,7 @@ export {
|
||||||
ɵɵelementContainerEnd,
|
ɵɵelementContainerEnd,
|
||||||
ɵɵelementContainer,
|
ɵɵelementContainer,
|
||||||
ɵɵstyleMap,
|
ɵɵstyleMap,
|
||||||
|
ɵɵstyleSanitizer,
|
||||||
ɵɵclassMap,
|
ɵɵclassMap,
|
||||||
ɵɵclassMapInterpolate1,
|
ɵɵclassMapInterpolate1,
|
||||||
ɵɵclassMapInterpolate2,
|
ɵɵclassMapInterpolate2,
|
||||||
|
|
|
@ -115,6 +115,7 @@ export {
|
||||||
ɵɵstylePropInterpolate8,
|
ɵɵstylePropInterpolate8,
|
||||||
ɵɵstylePropInterpolateV,
|
ɵɵstylePropInterpolateV,
|
||||||
|
|
||||||
|
ɵɵstyleSanitizer,
|
||||||
ɵɵtemplate,
|
ɵɵtemplate,
|
||||||
|
|
||||||
ɵɵtext,
|
ɵɵtext,
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
import {SafeValue} from '../../sanitization/bypass';
|
import {SafeValue} from '../../sanitization/bypass';
|
||||||
import {ɵɵdefaultStyleSanitizer} from '../../sanitization/sanitization';
|
|
||||||
import {StyleSanitizeFn} from '../../sanitization/style_sanitizer';
|
import {StyleSanitizeFn} from '../../sanitization/style_sanitizer';
|
||||||
import {throwErrorIfNoChangesMode} from '../errors';
|
import {throwErrorIfNoChangesMode} from '../errors';
|
||||||
import {setInputsForProperty} from '../instructions/shared';
|
import {setInputsForProperty} from '../instructions/shared';
|
||||||
|
@ -16,7 +15,7 @@ import {StylingMapArray, StylingMapArrayIndex, TStylingContext} from '../interfa
|
||||||
import {isDirectiveHost} from '../interfaces/type_checks';
|
import {isDirectiveHost} from '../interfaces/type_checks';
|
||||||
import {LView, RENDERER, TVIEW} from '../interfaces/view';
|
import {LView, RENDERER, TVIEW} from '../interfaces/view';
|
||||||
import {getActiveDirectiveId, getCheckNoChangesMode, getCurrentStyleSanitizer, getLView, getSelectedIndex, incrementBindingIndex, nextBindingIndex, resetCurrentStyleSanitizer, setCurrentStyleSanitizer, setElementExitFn} from '../state';
|
import {getActiveDirectiveId, getCheckNoChangesMode, getCurrentStyleSanitizer, getLView, getSelectedIndex, incrementBindingIndex, nextBindingIndex, resetCurrentStyleSanitizer, setCurrentStyleSanitizer, setElementExitFn} from '../state';
|
||||||
import {applyStylingMapDirectly, applyStylingValueDirectly, flushStyling, updateClassViaContext, updateStyleViaContext} from '../styling/bindings';
|
import {applyStylingMapDirectly, applyStylingValueDirectly, flushStyling, setClass, setStyle, updateClassViaContext, updateStyleViaContext} from '../styling/bindings';
|
||||||
import {activateStylingMapFeature} from '../styling/map_based_bindings';
|
import {activateStylingMapFeature} from '../styling/map_based_bindings';
|
||||||
import {attachStylingDebugObject} from '../styling/styling_debug';
|
import {attachStylingDebugObject} from '../styling/styling_debug';
|
||||||
import {NO_CHANGE} from '../tokens';
|
import {NO_CHANGE} from '../tokens';
|
||||||
|
@ -36,6 +35,26 @@ import {getNativeByTNode, getTNode} from '../util/view_utils';
|
||||||
* --------
|
* --------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the current style sanitizer function which will then be used
|
||||||
|
* within all follow-up prop and map-based style binding instructions
|
||||||
|
* for the given element.
|
||||||
|
*
|
||||||
|
* Note that once styling has been applied to the element (i.e. once
|
||||||
|
* `advance(n)` is executed or the hostBindings/template function exits)
|
||||||
|
* then the active `sanitizerFn` will be set to `null`. This means that
|
||||||
|
* once styling is applied to another element then a another call to
|
||||||
|
* `styleSanitizer` will need to be made.
|
||||||
|
*
|
||||||
|
* @param sanitizerFn The sanitization function that will be used to
|
||||||
|
* process style prop/value entries.
|
||||||
|
*
|
||||||
|
* @codeGenApi
|
||||||
|
*/
|
||||||
|
export function ɵɵstyleSanitizer(sanitizer: StyleSanitizeFn | null): void {
|
||||||
|
setCurrentStyleSanitizer(sanitizer);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update a style binding on an element with the provided value.
|
* Update a style binding on an element with the provided value.
|
||||||
*
|
*
|
||||||
|
@ -59,8 +78,8 @@ import {getNativeByTNode, getTNode} from '../util/view_utils';
|
||||||
*/
|
*/
|
||||||
export function ɵɵstyleProp(
|
export function ɵɵstyleProp(
|
||||||
prop: string, value: string | number | SafeValue | null,
|
prop: string, value: string | number | SafeValue | null,
|
||||||
suffixOrSanitizer?: StyleSanitizeFn | string | null): typeof ɵɵstyleProp {
|
suffix?: string | null): typeof ɵɵstyleProp {
|
||||||
stylePropInternal(getSelectedIndex(), prop, value, suffixOrSanitizer);
|
stylePropInternal(getSelectedIndex(), prop, value, suffix);
|
||||||
return ɵɵstyleProp;
|
return ɵɵstyleProp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,7 +91,7 @@ export function ɵɵstyleProp(
|
||||||
*/
|
*/
|
||||||
export function stylePropInternal(
|
export function stylePropInternal(
|
||||||
elementIndex: number, prop: string, value: string | number | SafeValue | null,
|
elementIndex: number, prop: string, value: string | number | SafeValue | null,
|
||||||
suffixOrSanitizer?: StyleSanitizeFn | string | null): void {
|
suffix?: string | null | undefined): void {
|
||||||
// if a value is interpolated then it may render a `NO_CHANGE` value.
|
// if a value is interpolated then it may render a `NO_CHANGE` value.
|
||||||
// in this case we do not need to do anything, but the binding index
|
// in this case we do not need to do anything, but the binding index
|
||||||
// still needs to be incremented because all styling binding values
|
// still needs to be incremented because all styling binding values
|
||||||
|
@ -90,12 +109,9 @@ export function stylePropInternal(
|
||||||
patchHostStylingFlag(tNode, isHostStyling(), false);
|
patchHostStylingFlag(tNode, isHostStyling(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
const isString = typeof suffixOrSanitizer === 'string';
|
|
||||||
const suffix = isString ? (suffixOrSanitizer as string) : null;
|
|
||||||
const sanitizer = isString ? null : (suffixOrSanitizer as StyleSanitizeFn | null | undefined);
|
|
||||||
const updated = stylingProp(
|
const updated = stylingProp(
|
||||||
tNode, firstUpdatePass, lView, bindingIndex, prop, resolveStylePropValue(value, suffix),
|
tNode, firstUpdatePass, lView, bindingIndex, prop, resolveStylePropValue(value, suffix),
|
||||||
false, sanitizer);
|
false);
|
||||||
if (ngDevMode) {
|
if (ngDevMode) {
|
||||||
ngDevMode.styleProp++;
|
ngDevMode.styleProp++;
|
||||||
if (updated) {
|
if (updated) {
|
||||||
|
@ -138,8 +154,7 @@ export function ɵɵclassProp(className: string, value: boolean | null): typeof
|
||||||
patchHostStylingFlag(tNode, isHostStyling(), true);
|
patchHostStylingFlag(tNode, isHostStyling(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
const updated =
|
const updated = stylingProp(tNode, firstUpdatePass, lView, bindingIndex, className, value, true);
|
||||||
stylingProp(tNode, firstUpdatePass, lView, bindingIndex, className, value, true, null);
|
|
||||||
if (ngDevMode) {
|
if (ngDevMode) {
|
||||||
ngDevMode.classProp++;
|
ngDevMode.classProp++;
|
||||||
if (updated) {
|
if (updated) {
|
||||||
|
@ -162,15 +177,12 @@ export function ɵɵclassProp(className: string, value: boolean | null): typeof
|
||||||
function stylingProp(
|
function stylingProp(
|
||||||
tNode: TNode, firstUpdatePass: boolean, lView: LView, bindingIndex: number, prop: string,
|
tNode: TNode, firstUpdatePass: boolean, lView: LView, bindingIndex: number, prop: string,
|
||||||
value: boolean | number | SafeValue | string | null | undefined | NO_CHANGE,
|
value: boolean | number | SafeValue | string | null | undefined | NO_CHANGE,
|
||||||
isClassBased: boolean, sanitizer: StyleSanitizeFn | null | undefined): boolean {
|
isClassBased: boolean): boolean {
|
||||||
let updated = false;
|
let updated = false;
|
||||||
|
|
||||||
if (sanitizer) {
|
|
||||||
setCurrentStyleSanitizer(sanitizer);
|
|
||||||
}
|
|
||||||
|
|
||||||
const native = getNativeByTNode(tNode, lView) as RElement;
|
const native = getNativeByTNode(tNode, lView) as RElement;
|
||||||
const context = isClassBased ? getClassesContext(tNode) : getStylesContext(tNode);
|
const context = isClassBased ? getClassesContext(tNode) : getStylesContext(tNode);
|
||||||
|
const sanitizer = isClassBased ? null : getCurrentStyleSanitizer();
|
||||||
|
|
||||||
// [style.prop] and [class.name] bindings do not use `bind()` and will
|
// [style.prop] and [class.name] bindings do not use `bind()` and will
|
||||||
// therefore manage accessing and updating the new value in the lView directly.
|
// therefore manage accessing and updating the new value in the lView directly.
|
||||||
|
@ -271,8 +283,7 @@ export function ɵɵstyleMap(styles: {[styleName: string]: any} | NO_CHANGE | nu
|
||||||
}
|
}
|
||||||
|
|
||||||
stylingMap(
|
stylingMap(
|
||||||
context, tNode, firstUpdatePass, lView, bindingIndex, styles, false, hasDirectiveInput,
|
context, tNode, firstUpdatePass, lView, bindingIndex, styles, false, hasDirectiveInput);
|
||||||
ɵɵdefaultStyleSanitizer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -335,7 +346,7 @@ export function classMapInternal(
|
||||||
}
|
}
|
||||||
|
|
||||||
stylingMap(
|
stylingMap(
|
||||||
context, tNode, firstUpdatePass, lView, bindingIndex, classes, true, hasDirectiveInput, null);
|
context, tNode, firstUpdatePass, lView, bindingIndex, classes, true, hasDirectiveInput);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -347,11 +358,11 @@ export function classMapInternal(
|
||||||
function stylingMap(
|
function stylingMap(
|
||||||
context: TStylingContext, tNode: TNode, firstUpdatePass: boolean, lView: LView,
|
context: TStylingContext, tNode: TNode, firstUpdatePass: boolean, lView: LView,
|
||||||
bindingIndex: number, value: {[key: string]: any} | string | null, isClassBased: boolean,
|
bindingIndex: number, value: {[key: string]: any} | string | null, isClassBased: boolean,
|
||||||
hasDirectiveInput: boolean, sanitizer: StyleSanitizeFn | null): void {
|
hasDirectiveInput: boolean): void {
|
||||||
const directiveIndex = getActiveDirectiveId();
|
const directiveIndex = getActiveDirectiveId();
|
||||||
const native = getNativeByTNode(tNode, lView) as RElement;
|
const native = getNativeByTNode(tNode, lView) as RElement;
|
||||||
const oldValue = getValue(lView, bindingIndex);
|
const oldValue = getValue(lView, bindingIndex);
|
||||||
setCurrentStyleSanitizer(ɵɵdefaultStyleSanitizer);
|
const sanitizer = getCurrentStyleSanitizer();
|
||||||
const valueHasChanged = hasValueChanged(oldValue, value);
|
const valueHasChanged = hasValueChanged(oldValue, value);
|
||||||
|
|
||||||
// [style] and [class] bindings do not use `bind()` and will therefore
|
// [style] and [class] bindings do not use `bind()` and will therefore
|
||||||
|
|
|
@ -297,14 +297,12 @@ import {LView} from './view';
|
||||||
*
|
*
|
||||||
* It is enabled in two cases:
|
* It is enabled in two cases:
|
||||||
*
|
*
|
||||||
* 1. One or more styleProp instructions are generated (a sanitizer is passed in to each one).
|
* 1. The `styleSanitizer(sanitizerFn)` instruction was called (just before any other
|
||||||
|
* styling instructions are run).
|
||||||
*
|
*
|
||||||
* 2. the `styleMap` instruction runs (it uses it by default internally).
|
* 2. The component/directive `LView` instance has a sanitizer object attached to it
|
||||||
*
|
* (this happens when `renderComponent` is executed with a `sanitizer` value or
|
||||||
* Sanitization can be enabled in the cases above, however, if a sanitizer is attached
|
* if the ngModule contains a sanitizer provider attached to it).
|
||||||
* in the `LView` then that sanitizer can be used to override whatever sanitizer is
|
|
||||||
* passed in the examples above (this happens when `renderComponent` is executed with a
|
|
||||||
* `sanitizer` value or if the ngModule contains a sanitizer provider attached to it).
|
|
||||||
*
|
*
|
||||||
* If and when sanitization is active then all property/value entries will be evaluated
|
* If and when sanitization is active then all property/value entries will be evaluated
|
||||||
* through the active sanitizer before they are applied to the element (or the styling
|
* through the active sanitizer before they are applied to the element (or the styling
|
||||||
|
@ -312,6 +310,18 @@ import {LView} from './view';
|
||||||
*
|
*
|
||||||
* If a `Sanitizer` object is used (via the `LView[SANITIZER]` value) then that object
|
* If a `Sanitizer` object is used (via the `LView[SANITIZER]` value) then that object
|
||||||
* will be used for every property.
|
* will be used for every property.
|
||||||
|
*
|
||||||
|
* If a `StyleSanitizerFn` function is used (via the `styleSanitizer`) then it will be
|
||||||
|
* called in two ways:
|
||||||
|
*
|
||||||
|
* 1. property validation mode: this will be called early to mark whether a property
|
||||||
|
* should be sanitized or not at during the flushing stage.
|
||||||
|
*
|
||||||
|
* 2. value sanitization mode: this will be called during the flushing stage and will
|
||||||
|
* run the sanitizer function against the value before applying it to the element.
|
||||||
|
*
|
||||||
|
* If sanitization returns an empty value then that empty value will be applied
|
||||||
|
* to the element.
|
||||||
*/
|
*/
|
||||||
export interface TStylingContext extends
|
export interface TStylingContext extends
|
||||||
Array<number|string|number|boolean|null|StylingMapArray|{}> {
|
Array<number|string|number|boolean|null|StylingMapArray|{}> {
|
||||||
|
|
|
@ -129,6 +129,7 @@ export const angularCoreEnv: {[name: string]: Function} =
|
||||||
'ɵɵstylePropInterpolate7': r3.ɵɵstylePropInterpolate7,
|
'ɵɵstylePropInterpolate7': r3.ɵɵstylePropInterpolate7,
|
||||||
'ɵɵstylePropInterpolate8': r3.ɵɵstylePropInterpolate8,
|
'ɵɵstylePropInterpolate8': r3.ɵɵstylePropInterpolate8,
|
||||||
'ɵɵstylePropInterpolateV': r3.ɵɵstylePropInterpolateV,
|
'ɵɵstylePropInterpolateV': r3.ɵɵstylePropInterpolateV,
|
||||||
|
'ɵɵstyleSanitizer': r3.ɵɵstyleSanitizer,
|
||||||
'ɵɵclassProp': r3.ɵɵclassProp,
|
'ɵɵclassProp': r3.ɵɵclassProp,
|
||||||
'ɵɵselect': r3.ɵɵselect,
|
'ɵɵselect': r3.ɵɵselect,
|
||||||
'ɵɵadvance': r3.ɵɵadvance,
|
'ɵɵadvance': r3.ɵɵadvance,
|
||||||
|
|
|
@ -97,8 +97,7 @@ export function updateStyleViaContext(
|
||||||
context: TStylingContext, tNode: TStylingNode, data: LStylingData, element: RElement,
|
context: TStylingContext, tNode: TStylingNode, data: LStylingData, element: RElement,
|
||||||
directiveIndex: number, prop: string | null, bindingIndex: number,
|
directiveIndex: number, prop: string | null, bindingIndex: number,
|
||||||
value: string | number | SafeValue | null | undefined | StylingMapArray | NO_CHANGE,
|
value: string | number | SafeValue | null | undefined | StylingMapArray | NO_CHANGE,
|
||||||
sanitizer: StyleSanitizeFn | null | undefined, forceUpdate: boolean,
|
sanitizer: StyleSanitizeFn | null, forceUpdate: boolean, firstUpdatePass: boolean): boolean {
|
||||||
firstUpdatePass: boolean): boolean {
|
|
||||||
const isMapBased = !prop;
|
const isMapBased = !prop;
|
||||||
const state = getStylingState(element, directiveIndex);
|
const state = getStylingState(element, directiveIndex);
|
||||||
const countIndex = isMapBased ? STYLING_INDEX_FOR_MAP_BINDING : state.stylesIndex++;
|
const countIndex = isMapBased ? STYLING_INDEX_FOR_MAP_BINDING : state.stylesIndex++;
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
import {NgForOfContext} from '@angular/common';
|
import {NgForOfContext} from '@angular/common';
|
||||||
|
|
||||||
import {ɵɵdefineComponent} from '../../src/render3/definition';
|
import {ɵɵdefineComponent} from '../../src/render3/definition';
|
||||||
import {RenderFlags, ɵɵattribute, ɵɵclassMap, ɵɵelement, ɵɵelementEnd, ɵɵelementStart, ɵɵproperty, ɵɵselect, ɵɵstyleMap, ɵɵstyleProp, ɵɵtemplate, ɵɵtext, ɵɵtextInterpolate1} from '../../src/render3/index';
|
import {RenderFlags, ɵɵattribute, ɵɵclassMap, ɵɵelement, ɵɵelementEnd, ɵɵelementStart, ɵɵproperty, ɵɵselect, ɵɵstyleMap, ɵɵstyleProp, ɵɵstyleSanitizer, ɵɵtemplate, ɵɵtext, ɵɵtextInterpolate1} from '../../src/render3/index';
|
||||||
import {AttributeMarker} from '../../src/render3/interfaces/node';
|
import {AttributeMarker} from '../../src/render3/interfaces/node';
|
||||||
import {bypassSanitizationTrustHtml, bypassSanitizationTrustResourceUrl, bypassSanitizationTrustScript, bypassSanitizationTrustStyle, bypassSanitizationTrustUrl, getSanitizationBypassType, unwrapSafeValue} from '../../src/sanitization/bypass';
|
import {bypassSanitizationTrustHtml, bypassSanitizationTrustResourceUrl, bypassSanitizationTrustScript, bypassSanitizationTrustStyle, bypassSanitizationTrustUrl, getSanitizationBypassType, unwrapSafeValue} from '../../src/sanitization/bypass';
|
||||||
import {ɵɵdefaultStyleSanitizer, ɵɵsanitizeHtml, ɵɵsanitizeResourceUrl, ɵɵsanitizeScript, ɵɵsanitizeStyle, ɵɵsanitizeUrl} from '../../src/sanitization/sanitization';
|
import {ɵɵdefaultStyleSanitizer, ɵɵsanitizeHtml, ɵɵsanitizeResourceUrl, ɵɵsanitizeScript, ɵɵsanitizeStyle, ɵɵsanitizeUrl} from '../../src/sanitization/sanitization';
|
||||||
|
@ -137,22 +137,20 @@ describe('instructions', () => {
|
||||||
|
|
||||||
describe('styleProp', () => {
|
describe('styleProp', () => {
|
||||||
it('should automatically sanitize unless a bypass operation is applied', () => {
|
it('should automatically sanitize unless a bypass operation is applied', () => {
|
||||||
const t = new TemplateFixture(
|
const t = new TemplateFixture(() => { return createDiv(); }, () => {}, 1);
|
||||||
() => { return createDiv(); },
|
t.update(() => {
|
||||||
() => {
|
ɵɵstyleSanitizer(ɵɵdefaultStyleSanitizer);
|
||||||
ɵɵstyleProp('background-image', 'url("http://server")', ɵɵdefaultStyleSanitizer);
|
ɵɵstyleProp('background-image', 'url("http://server")');
|
||||||
},
|
});
|
||||||
1);
|
// nothing is set because sanitizer suppresses it.
|
||||||
|
expect(t.html).toEqual('<div></div>');
|
||||||
const element = t.hostElement.firstChild as HTMLElement;
|
|
||||||
expect(element.style.getPropertyValue('background-image')).toEqual('');
|
|
||||||
|
|
||||||
t.update(() => {
|
t.update(() => {
|
||||||
ɵɵstyleProp(
|
ɵɵstyleSanitizer(ɵɵdefaultStyleSanitizer);
|
||||||
'background-image', bypassSanitizationTrustStyle('url("http://server2")'),
|
ɵɵstyleProp('background-image', bypassSanitizationTrustStyle('url("http://server2")'));
|
||||||
ɵɵdefaultStyleSanitizer);
|
|
||||||
});
|
});
|
||||||
expect(element.style.getPropertyValue('background-image')).toEqual('url("http://server2")');
|
expect((t.hostElement.firstChild as HTMLElement).style.getPropertyValue('background-image'))
|
||||||
|
.toEqual('url("http://server2")');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -162,14 +160,10 @@ describe('instructions', () => {
|
||||||
function createDivWithStyle() { ɵɵelement(0, 'div', 0); }
|
function createDivWithStyle() { ɵɵelement(0, 'div', 0); }
|
||||||
|
|
||||||
it('should add style', () => {
|
it('should add style', () => {
|
||||||
const fixture = new TemplateFixture(createDivWithStyle, () => {
|
const fixture = new TemplateFixture(
|
||||||
ɵɵstyleMap({'background-color': 'red'});
|
createDivWithStyle, () => {}, 1, 0, null, null, null, undefined, attrs);
|
||||||
}, 1, 0, null, null, null, undefined, attrs);
|
fixture.update(() => { ɵɵstyleMap({'background-color': 'red'}); });
|
||||||
fixture.update();
|
expect(fixture.html).toEqual('<div style="background-color: red; height: 10px;"></div>');
|
||||||
const targetDiv = fixture.hostElement.querySelector('div') !;
|
|
||||||
const style = targetDiv.style as{[key: string]: any};
|
|
||||||
expect(style['background-color']).toEqual('red');
|
|
||||||
expect(style['height']).toEqual('10px');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should sanitize new styles that may contain `url` properties', () => {
|
it('should sanitize new styles that may contain `url` properties', () => {
|
||||||
|
@ -179,6 +173,7 @@ describe('instructions', () => {
|
||||||
const fixture = new TemplateFixture(
|
const fixture = new TemplateFixture(
|
||||||
() => { return createDiv(); }, //
|
() => { return createDiv(); }, //
|
||||||
() => {
|
() => {
|
||||||
|
ɵɵstyleSanitizer(sanitizerInterceptor.getStyleSanitizer());
|
||||||
ɵɵstyleMap({
|
ɵɵstyleMap({
|
||||||
'background-image': 'background-image',
|
'background-image': 'background-image',
|
||||||
'background': 'background',
|
'background': 'background',
|
||||||
|
|
|
@ -1037,7 +1037,7 @@ export declare function ɵɵstyleMap(styles: {
|
||||||
[styleName: string]: any;
|
[styleName: string]: any;
|
||||||
} | NO_CHANGE | null): void;
|
} | NO_CHANGE | null): void;
|
||||||
|
|
||||||
export declare function ɵɵstyleProp(prop: string, value: string | number | SafeValue | null, suffixOrSanitizer?: StyleSanitizeFn | string | null): typeof ɵɵstyleProp;
|
export declare function ɵɵstyleProp(prop: string, value: string | number | SafeValue | null, suffix?: string | null): typeof ɵɵstyleProp;
|
||||||
|
|
||||||
export declare function ɵɵstylePropInterpolate1(prop: string, prefix: string, v0: any, suffix: string, valueSuffix?: string | null): typeof ɵɵstylePropInterpolate1;
|
export declare function ɵɵstylePropInterpolate1(prop: string, prefix: string, v0: any, suffix: string, valueSuffix?: string | null): typeof ɵɵstylePropInterpolate1;
|
||||||
|
|
||||||
|
@ -1057,6 +1057,8 @@ export declare function ɵɵstylePropInterpolate8(prop: string, prefix: string,
|
||||||
|
|
||||||
export declare function ɵɵstylePropInterpolateV(prop: string, values: any[], valueSuffix?: string | null): typeof ɵɵstylePropInterpolateV;
|
export declare function ɵɵstylePropInterpolateV(prop: string, values: any[], valueSuffix?: string | null): typeof ɵɵstylePropInterpolateV;
|
||||||
|
|
||||||
|
export declare function ɵɵstyleSanitizer(sanitizer: StyleSanitizeFn | null): void;
|
||||||
|
|
||||||
export declare function ɵɵtemplate(index: number, templateFn: ComponentTemplate<any> | null, decls: number, vars: number, tagName?: string | null, attrsIndex?: number | null, localRefsIndex?: number | null, localRefExtractor?: LocalRefExtractor): void;
|
export declare function ɵɵtemplate(index: number, templateFn: ComponentTemplate<any> | null, decls: number, vars: number, tagName?: string | null, attrsIndex?: number | null, localRefsIndex?: number | null, localRefExtractor?: LocalRefExtractor): void;
|
||||||
|
|
||||||
export declare function ɵɵtemplateRefExtractor(tNode: TNode, currentView: LView): ViewEngine_TemplateRef<unknown> | null;
|
export declare function ɵɵtemplateRefExtractor(tNode: TNode, currentView: LView): ViewEngine_TemplateRef<unknown> | null;
|
||||||
|
|
Loading…
Reference in New Issue