refactor(ivy): move classMap interpolation logic internally (#31211)
Adds the new `classMapInterpolate1` through `classMapInterpolate8` instructions which handle interpolations inside the `class` attribute and moves the interpolation logic internally. This allows us to remove the `interpolationX` instructions in a follow-up PR. These changes also add an error if an interpolation is encountered inside a `style` tag (e.g. `style="width: {{value}}"`). Up until now this would actually generate valid instructions, because `styleMap` goes through the same code path as `classMap` which does support interpolation. At runtime, however, `styleMap` would set invalid styles that look like `<div style="0:w;1:i;2:d;3:t;4:h;5::;7:1;">`. In `ViewEngine` interpolations inside `style` weren't supported either, however there we'd output invalid styles like `<div style="unsafe">`, even if the content was trusted. PR Close #31211
This commit is contained in:

committed by
Alex Rickabaugh

parent
dca713c087
commit
02491a6ce8
@ -36,8 +36,8 @@ import {I18nContext} from './i18n/context';
|
||||
import {I18nMetaVisitor} from './i18n/meta';
|
||||
import {getSerializedI18nContent} from './i18n/serializer';
|
||||
import {I18N_ICU_MAPPING_PREFIX, TRANSLATION_PREFIX, assembleBoundTextPlaceholders, assembleI18nBoundString, formatI18nPlaceholderName, getTranslationConstPrefix, getTranslationDeclStmts, icuFromI18nMessage, isI18nRootNode, isSingleI18nIcu, metaFromI18nMessage, placeholdersToParams, wrapI18nPlaceholder} from './i18n/util';
|
||||
import {Instruction, StylingBuilder} from './styling_builder';
|
||||
import {CONTEXT_NAME, IMPLICIT_REFERENCE, NON_BINDABLE_ATTR, REFERENCE_PREFIX, RENDER_FLAGS, asLiteral, chainedInstruction, getAttrsForDirectiveMatching, invalid, trimTrailingNulls, unsupported} from './util';
|
||||
import {StylingBuilder, StylingInstruction} from './styling_builder';
|
||||
import {CONTEXT_NAME, IMPLICIT_REFERENCE, NON_BINDABLE_ATTR, REFERENCE_PREFIX, RENDER_FLAGS, asLiteral, chainedInstruction, getAttrsForDirectiveMatching, getInterpolationArgsLength, invalid, trimTrailingNulls, unsupported} from './util';
|
||||
|
||||
|
||||
|
||||
@ -1067,14 +1067,21 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
|
||||
}
|
||||
|
||||
private processStylingInstruction(
|
||||
elementIndex: number, instruction: Instruction|null, createMode: boolean) {
|
||||
elementIndex: number, instruction: StylingInstruction|null, createMode: boolean) {
|
||||
if (instruction) {
|
||||
const paramsFn = () => instruction.buildParams(value => this.convertPropertyBinding(value));
|
||||
if (createMode) {
|
||||
this.creationInstruction(instruction.sourceSpan, instruction.reference, paramsFn);
|
||||
this.creationInstruction(instruction.sourceSpan, instruction.reference, () => {
|
||||
return instruction.params(value => this.convertPropertyBinding(value)) as o.Expression[];
|
||||
});
|
||||
} else {
|
||||
this.updateInstruction(
|
||||
elementIndex, instruction.sourceSpan, instruction.reference, paramsFn);
|
||||
this.updateInstruction(elementIndex, instruction.sourceSpan, instruction.reference, () => {
|
||||
return instruction
|
||||
.params(value => {
|
||||
return (instruction.supportsInterpolation && value instanceof Interpolation) ?
|
||||
this.getUpdateInstructionArguments(value) :
|
||||
this.convertPropertyBinding(value);
|
||||
}) as o.Expression[];
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1150,12 +1157,9 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
|
||||
}
|
||||
|
||||
private convertPropertyBinding(value: AST): o.Expression {
|
||||
const interpolationFn =
|
||||
value instanceof Interpolation ? interpolate : () => error('Unexpected interpolation');
|
||||
|
||||
const convertedPropertyBinding = convertPropertyBinding(
|
||||
this, this.getImplicitReceiverExpr(), value, this.bindingContext(), BindingForm.TrySimple,
|
||||
interpolationFn);
|
||||
() => error('Unexpected interpolation'));
|
||||
const valExpr = convertedPropertyBinding.currValExpr;
|
||||
this._tempVariables.push(...convertedPropertyBinding.stmts);
|
||||
|
||||
@ -1751,31 +1755,6 @@ function getNgProjectAsLiteral(attribute: t.TextAttribute): o.Expression[] {
|
||||
return [o.literal(core.AttributeMarker.ProjectAs), asLiteral(parsedR3Selector)];
|
||||
}
|
||||
|
||||
function interpolate(args: o.Expression[]): o.Expression {
|
||||
args = args.slice(1); // Ignore the length prefix added for render2
|
||||
switch (args.length) {
|
||||
case 3:
|
||||
return o.importExpr(R3.interpolation1).callFn(args);
|
||||
case 5:
|
||||
return o.importExpr(R3.interpolation2).callFn(args);
|
||||
case 7:
|
||||
return o.importExpr(R3.interpolation3).callFn(args);
|
||||
case 9:
|
||||
return o.importExpr(R3.interpolation4).callFn(args);
|
||||
case 11:
|
||||
return o.importExpr(R3.interpolation5).callFn(args);
|
||||
case 13:
|
||||
return o.importExpr(R3.interpolation6).callFn(args);
|
||||
case 15:
|
||||
return o.importExpr(R3.interpolation7).callFn(args);
|
||||
case 17:
|
||||
return o.importExpr(R3.interpolation8).callFn(args);
|
||||
}
|
||||
(args.length >= 19 && args.length % 2 == 1) ||
|
||||
error(`Invalid interpolation argument length ${args.length}`);
|
||||
return o.importExpr(R3.interpolationV).callFn([o.literalArr(args)]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the instruction to generate for an interpolated property
|
||||
* @param interpolation An Interpolation AST
|
||||
@ -1861,22 +1840,6 @@ function getTextInterpolationExpression(interpolation: Interpolation): o.Externa
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of arguments expected to be passed to a generated instruction in the case of
|
||||
* interpolation instructions.
|
||||
* @param interpolation An interpolation ast
|
||||
*/
|
||||
function getInterpolationArgsLength(interpolation: Interpolation) {
|
||||
const {expressions, strings} = interpolation;
|
||||
if (expressions.length === 1 && strings.length === 2 && strings[0] === '' && strings[1] === '') {
|
||||
// If the interpolation has one interpolated value, but the prefix and suffix are both empty
|
||||
// strings, we only pass one argument, to a special instruction like `propertyInterpolate` or
|
||||
// `textInterpolate`.
|
||||
return 1;
|
||||
} else {
|
||||
return expressions.length + strings.length;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Options that can be used to modify how a template is parsed by `parseTemplate()`.
|
||||
*/
|
||||
|
Reference in New Issue
Block a user