refactor(ivy): remove styleSanitizer instruction in favor of an inline param (#34480)
This patch removes the need for the styleSanitizer() instruction in favor of passing the sanitizer into directly into the styleProp instruction. This patch also increases the binding index size for all style/class bindings in preparation for #34418 PR Close #34480
This commit is contained in:
parent
0d8309509b
commit
84d24c08e1
|
@ -377,7 +377,6 @@ 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -511,7 +510,6 @@ 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);
|
||||||
|
@ -557,8 +555,7 @@ describe('compiler compliance: styling', () => {
|
||||||
$r3$.ɵɵelement(0, "div");
|
$r3$.ɵɵelement(0, "div");
|
||||||
}
|
}
|
||||||
if (rf & 2) {
|
if (rf & 2) {
|
||||||
$r3$.ɵɵstyleSanitizer($r3$.ɵɵdefaultStyleSanitizer);
|
$r3$.ɵɵstyleProp("background-image", ctx.myImage, $r3$.ɵɵdefaultStyleSanitizer);
|
||||||
$r3$.ɵɵstyleProp("background-image", ctx.myImage);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
encapsulation: 2
|
encapsulation: 2
|
||||||
|
@ -816,7 +813,6 @@ 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);
|
||||||
}
|
}
|
||||||
|
@ -858,7 +854,6 @@ 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));
|
||||||
}
|
}
|
||||||
|
@ -911,7 +906,6 @@ 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));
|
||||||
|
@ -1017,7 +1011,6 @@ 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);
|
||||||
|
@ -1075,7 +1068,6 @@ 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);
|
||||||
|
@ -1133,7 +1125,6 @@ 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);
|
||||||
|
@ -1148,7 +1139,6 @@ 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);
|
||||||
|
@ -1424,6 +1414,46 @@ 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 = {
|
||||||
|
@ -1849,7 +1879,6 @@ 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);
|
||||||
}
|
}
|
||||||
|
@ -1902,7 +1931,7 @@ describe('compiler compliance: styling', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('new styling refactor', () => {
|
describe('new styling refactor', () => {
|
||||||
it('should generate a `styleSanitizer` instruction when one or more sanitizable style properties are statically detected',
|
it('should generate a sanitizer value into the instruction when one or more sanitizable style properties are statically detected',
|
||||||
() => {
|
() => {
|
||||||
const files = {
|
const files = {
|
||||||
app: {
|
app: {
|
||||||
|
@ -1926,8 +1955,7 @@ describe('compiler compliance: styling', () => {
|
||||||
template: function MyAppComp_Template(rf, ctx) {
|
template: function MyAppComp_Template(rf, ctx) {
|
||||||
…
|
…
|
||||||
if (rf & 2) {
|
if (rf & 2) {
|
||||||
$r3$.ɵɵstyleSanitizer($r3$.ɵɵdefaultStyleSanitizer);
|
$r3$.ɵɵstyleProp("background-image", ctx.bgExp, $r3$.ɵɵdefaultStyleSanitizer);
|
||||||
$r3$.ɵɵstyleProp("background-image", ctx.bgExp);
|
|
||||||
}
|
}
|
||||||
…
|
…
|
||||||
}
|
}
|
||||||
|
@ -1937,8 +1965,7 @@ describe('compiler compliance: styling', () => {
|
||||||
expectEmit(result.source, template, 'Incorrect template');
|
expectEmit(result.source, template, 'Incorrect template');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should generate a `styleSanitizer` instruction when a `styleMap` instruction is used',
|
it('should not add a sanitizer param when a `styleMap` instruction is used', () => {
|
||||||
() => {
|
|
||||||
const files = {
|
const files = {
|
||||||
app: {
|
app: {
|
||||||
'spec.ts': `
|
'spec.ts': `
|
||||||
|
@ -1961,7 +1988,6 @@ describe('compiler compliance: styling', () => {
|
||||||
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);
|
||||||
}
|
}
|
||||||
…
|
…
|
||||||
|
@ -1972,7 +1998,7 @@ describe('compiler compliance: styling', () => {
|
||||||
expectEmit(result.source, template, 'Incorrect template');
|
expectEmit(result.source, template, 'Incorrect template');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('shouldn\'t generate a `styleSanitizer` instruction when class-based instructions are used',
|
it('shouldn\'t generate a sanitizer param into the styling instruction when class-based instructions are used',
|
||||||
() => {
|
() => {
|
||||||
const files = {
|
const files = {
|
||||||
app: {
|
app: {
|
||||||
|
|
|
@ -113,8 +113,6 @@ 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,6 +44,7 @@ interface BoundStylingEntry {
|
||||||
name: string|null;
|
name: string|null;
|
||||||
unit: string|null;
|
unit: string|null;
|
||||||
sourceSpan: ParseSourceSpan;
|
sourceSpan: ParseSourceSpan;
|
||||||
|
sanitize: boolean;
|
||||||
value: AST;
|
value: AST;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,10 +117,6 @@ 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) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -179,14 +176,13 @@ 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;
|
||||||
|
@ -202,8 +198,8 @@ export class StylingBuilder {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const {property, hasOverrideFlag} = parseProperty(name);
|
const {property, hasOverrideFlag} = parseProperty(name);
|
||||||
const entry:
|
const entry: BoundStylingEntry =
|
||||||
BoundStylingEntry = {name: property, value, sourceSpan, hasOverrideFlag, unit: null};
|
{name: property, value, sourceSpan, sanitize: false, hasOverrideFlag, unit: null};
|
||||||
if (isMapBased) {
|
if (isMapBased) {
|
||||||
if (this._classMapInput) {
|
if (this._classMapInput) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
|
@ -364,10 +360,9 @@ export class StylingBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
private _buildSingleInputs(
|
private _buildSingleInputs(
|
||||||
reference: o.ExternalReference, inputs: BoundStylingEntry[], mapIndex: Map<string, number>,
|
reference: o.ExternalReference, inputs: BoundStylingEntry[], valueConverter: ValueConverter,
|
||||||
allowUnits: boolean, valueConverter: ValueConverter,
|
getInterpolationExpressionFn: ((value: Interpolation) => o.ExternalReference)|null,
|
||||||
getInterpolationExpressionFn?: (value: Interpolation) => o.ExternalReference):
|
isClassBased: boolean): StylingInstruction[] {
|
||||||
StylingInstruction[] {
|
|
||||||
const instructions: StylingInstruction[] = [];
|
const instructions: StylingInstruction[] = [];
|
||||||
|
|
||||||
inputs.forEach(input => {
|
inputs.forEach(input => {
|
||||||
|
@ -390,7 +385,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)
|
// params => stylingProp(propName, value, suffix|sanitizer)
|
||||||
const params: o.Expression[] = [];
|
const params: o.Expression[] = [];
|
||||||
params.push(o.literal(input.name));
|
params.push(o.literal(input.name));
|
||||||
|
|
||||||
|
@ -401,8 +396,16 @@ export class StylingBuilder {
|
||||||
params.push(convertResult);
|
params.push(convertResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (allowUnits && input.unit) {
|
// [style.prop] bindings may use suffix values (e.g. px, em, etc...) and they
|
||||||
|
// can also use a sanitizer. Sanitization occurs for url-based entries. Having
|
||||||
|
// 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));
|
params.push(o.literal(input.unit));
|
||||||
|
} else if (input.sanitize) {
|
||||||
|
params.push(o.importExpr(R3.defaultStyleSanitizer));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return params;
|
return params;
|
||||||
|
@ -427,7 +430,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, this._classesIndex, false, valueConverter);
|
R3.classProp, this._singleClassInputs, valueConverter, null, true);
|
||||||
}
|
}
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
@ -435,23 +438,12 @@ 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, this._stylesIndex, true, valueConverter,
|
R3.styleProp, this._singleStyleInputs, valueConverter,
|
||||||
getStylePropInterpolationExpression);
|
getStylePropInterpolationExpression, false);
|
||||||
}
|
}
|
||||||
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.
|
||||||
|
@ -459,9 +451,6 @@ 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,7 +122,6 @@ export {
|
||||||
ɵɵelementContainerEnd,
|
ɵɵelementContainerEnd,
|
||||||
ɵɵelementContainer,
|
ɵɵelementContainer,
|
||||||
ɵɵstyleMap,
|
ɵɵstyleMap,
|
||||||
ɵɵstyleSanitizer,
|
|
||||||
ɵɵclassMap,
|
ɵɵclassMap,
|
||||||
ɵɵclassMapInterpolate1,
|
ɵɵclassMapInterpolate1,
|
||||||
ɵɵclassMapInterpolate2,
|
ɵɵclassMapInterpolate2,
|
||||||
|
|
|
@ -115,7 +115,6 @@ export {
|
||||||
ɵɵstylePropInterpolate8,
|
ɵɵstylePropInterpolate8,
|
||||||
ɵɵstylePropInterpolateV,
|
ɵɵstylePropInterpolateV,
|
||||||
|
|
||||||
ɵɵstyleSanitizer,
|
|
||||||
ɵɵtemplate,
|
ɵɵtemplate,
|
||||||
|
|
||||||
ɵɵtext,
|
ɵɵtext,
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
* 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';
|
||||||
|
@ -15,7 +16,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, setClass, setStyle, updateClassViaContext, updateStyleViaContext} from '../styling/bindings';
|
import {applyStylingMapDirectly, applyStylingValueDirectly, flushStyling, 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';
|
||||||
|
@ -35,26 +36,6 @@ 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.
|
||||||
*
|
*
|
||||||
|
@ -78,8 +59,8 @@ export function ɵɵstyleSanitizer(sanitizer: StyleSanitizeFn | null): void {
|
||||||
*/
|
*/
|
||||||
export function ɵɵstyleProp(
|
export function ɵɵstyleProp(
|
||||||
prop: string, value: string | number | SafeValue | null,
|
prop: string, value: string | number | SafeValue | null,
|
||||||
suffix?: string | null): typeof ɵɵstyleProp {
|
suffixOrSanitizer?: StyleSanitizeFn | string | null): typeof ɵɵstyleProp {
|
||||||
stylePropInternal(getSelectedIndex(), prop, value, suffix);
|
stylePropInternal(getSelectedIndex(), prop, value, suffixOrSanitizer);
|
||||||
return ɵɵstyleProp;
|
return ɵɵstyleProp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,7 +72,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,
|
||||||
suffix?: string | null | undefined): void {
|
suffixOrSanitizer?: StyleSanitizeFn | string | null): 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
|
||||||
|
@ -109,9 +90,12 @@ 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);
|
false, sanitizer);
|
||||||
if (ngDevMode) {
|
if (ngDevMode) {
|
||||||
ngDevMode.styleProp++;
|
ngDevMode.styleProp++;
|
||||||
if (updated) {
|
if (updated) {
|
||||||
|
@ -154,7 +138,8 @@ export function ɵɵclassProp(className: string, value: boolean | null): typeof
|
||||||
patchHostStylingFlag(tNode, isHostStyling(), true);
|
patchHostStylingFlag(tNode, isHostStyling(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
const updated = stylingProp(tNode, firstUpdatePass, lView, bindingIndex, className, value, true);
|
const updated =
|
||||||
|
stylingProp(tNode, firstUpdatePass, lView, bindingIndex, className, value, true, null);
|
||||||
if (ngDevMode) {
|
if (ngDevMode) {
|
||||||
ngDevMode.classProp++;
|
ngDevMode.classProp++;
|
||||||
if (updated) {
|
if (updated) {
|
||||||
|
@ -177,12 +162,15 @@ 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): boolean {
|
isClassBased: boolean, sanitizer: StyleSanitizeFn | null | undefined): 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.
|
||||||
|
@ -283,7 +271,8 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -346,7 +335,7 @@ export function classMapInternal(
|
||||||
}
|
}
|
||||||
|
|
||||||
stylingMap(
|
stylingMap(
|
||||||
context, tNode, firstUpdatePass, lView, bindingIndex, classes, true, hasDirectiveInput);
|
context, tNode, firstUpdatePass, lView, bindingIndex, classes, true, hasDirectiveInput, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -358,11 +347,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): void {
|
hasDirectiveInput: boolean, sanitizer: StyleSanitizeFn | null): 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);
|
||||||
const sanitizer = getCurrentStyleSanitizer();
|
setCurrentStyleSanitizer(ɵɵdefaultStyleSanitizer);
|
||||||
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,12 +297,14 @@ import {LView} from './view';
|
||||||
*
|
*
|
||||||
* It is enabled in two cases:
|
* It is enabled in two cases:
|
||||||
*
|
*
|
||||||
* 1. The `styleSanitizer(sanitizerFn)` instruction was called (just before any other
|
* 1. One or more styleProp instructions are generated (a sanitizer is passed in to each one).
|
||||||
* styling instructions are run).
|
|
||||||
*
|
*
|
||||||
* 2. The component/directive `LView` instance has a sanitizer object attached to it
|
* 2. the `styleMap` instruction runs (it uses it by default internally).
|
||||||
* (this happens when `renderComponent` is executed with a `sanitizer` value or
|
*
|
||||||
* if the ngModule contains a sanitizer provider attached to it).
|
* Sanitization can be enabled in the cases above, however, if a sanitizer is attached
|
||||||
|
* 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
|
||||||
|
@ -310,18 +312,6 @@ 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,7 +129,6 @@ 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,7 +97,8 @@ 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, forceUpdate: boolean, firstUpdatePass: boolean): boolean {
|
sanitizer: StyleSanitizeFn | null | undefined, forceUpdate: 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, ɵɵstyleSanitizer, ɵɵtemplate, ɵɵtext, ɵɵtextInterpolate1} from '../../src/render3/index';
|
import {RenderFlags, ɵɵattribute, ɵɵclassMap, ɵɵelement, ɵɵelementEnd, ɵɵelementStart, ɵɵproperty, ɵɵselect, ɵɵstyleMap, ɵɵstyleProp, ɵɵ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,20 +137,22 @@ 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(() => { return createDiv(); }, () => {}, 1);
|
const t = new TemplateFixture(
|
||||||
t.update(() => {
|
() => { return createDiv(); },
|
||||||
ɵɵstyleSanitizer(ɵɵdefaultStyleSanitizer);
|
() => {
|
||||||
ɵɵstyleProp('background-image', 'url("http://server")');
|
ɵɵstyleProp('background-image', 'url("http://server")', ɵɵdefaultStyleSanitizer);
|
||||||
});
|
},
|
||||||
// nothing is set because sanitizer suppresses it.
|
1);
|
||||||
expect(t.html).toEqual('<div></div>');
|
|
||||||
|
const element = t.hostElement.firstChild as HTMLElement;
|
||||||
|
expect(element.style.getPropertyValue('background-image')).toEqual('');
|
||||||
|
|
||||||
t.update(() => {
|
t.update(() => {
|
||||||
ɵɵstyleSanitizer(ɵɵdefaultStyleSanitizer);
|
ɵɵstyleProp(
|
||||||
ɵɵstyleProp('background-image', bypassSanitizationTrustStyle('url("http://server2")'));
|
'background-image', bypassSanitizationTrustStyle('url("http://server2")'),
|
||||||
|
ɵɵdefaultStyleSanitizer);
|
||||||
});
|
});
|
||||||
expect((t.hostElement.firstChild as HTMLElement).style.getPropertyValue('background-image'))
|
expect(element.style.getPropertyValue('background-image')).toEqual('url("http://server2")');
|
||||||
.toEqual('url("http://server2")');
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -160,10 +162,14 @@ 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(
|
const fixture = new TemplateFixture(createDivWithStyle, () => {
|
||||||
createDivWithStyle, () => {}, 1, 0, null, null, null, undefined, attrs);
|
ɵɵstyleMap({'background-color': 'red'});
|
||||||
fixture.update(() => { ɵɵstyleMap({'background-color': 'red'}); });
|
}, 1, 0, null, null, null, undefined, attrs);
|
||||||
expect(fixture.html).toEqual('<div style="background-color: red; height: 10px;"></div>');
|
fixture.update();
|
||||||
|
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', () => {
|
||||||
|
@ -173,7 +179,6 @@ 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, suffix?: string | null): typeof ɵɵstyleProp;
|
export declare function ɵɵstyleProp(prop: string, value: string | number | SafeValue | null, suffixOrSanitizer?: StyleSanitizeFn | 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,8 +1057,6 @@ 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