Skip to content

Commit

Permalink
fixup! fix(compiler): compute correct offsets when interpolations hav…
Browse files Browse the repository at this point in the history
…e HTML entities
  • Loading branch information
atscott committed Jan 25, 2022
1 parent eae58a9 commit 7bfc719
Showing 1 changed file with 15 additions and 12 deletions.
27 changes: 15 additions & 12 deletions packages/compiler/src/expression_parser/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,8 @@ export class Parser {
const strings: InterpolationPiece[] = [];
const expressions: InterpolationPiece[] = [];
const offsets: number[] = [];
const inputToTemplateIndexMap =
interpolatedTokens ? getIndexMapForOriginalTemplate(interpolatedTokens) : null;
let i = 0;
let atInterpolation = false;
let extendLastString = false;
Expand Down Expand Up @@ -249,9 +251,10 @@ export class Parser {
`at column ${i} in`, location);
}
expressions.push({text, start: fullStart, end: fullEnd});
const offset = interpolatedTokens ?
computeOffsetInOriginalTemplate(fullStart, interpolatedTokens) + interpStart.length :
exprStart;
const startInOriginalTemplate = inputToTemplateIndexMap ?
(inputToTemplateIndexMap.get(fullStart) ?? fullStart) :
fullStart;
const offset = startInOriginalTemplate + interpStart.length;
offsets.push(offset);

i = fullEnd;
Expand Down Expand Up @@ -1305,26 +1308,25 @@ class SimpleExpressionChecker extends RecursiveAstVisitor {
}
}
/**
* Computes the real offset in the original template for a given input index in an interpolation.
* Computes the real offset in the original template for indexes in an interpolation.
*
* Because templates can have encoded HTML entities and the input passed to the parser at this stage
* of the compiler is the _decoded_ value, we need to compute the real offset using the original
* encoded values in the interpolated tokens. Note that this is only a special case handling for
* `MlParserTokenType.ENCODED_ENTITY` token types. All other interpolated tokens are expected to
* have parts which exactly match the input string for parsing the interpolation.
*
* @param exprStart The start of the expression being processed. This start location is the
* _decoded_ template input to the prase interpolation.
* @param interpolatedTokens The tokens for the interpolated value.
* @returns
*
* @returns A map of index locations in the decoded template to indexes in the original template
*/
function computeOffsetInOriginalTemplate(
exprStart: number,
interpolatedTokens: InterpolatedAttributeToken[]|InterpolatedTextToken[]): number {
function getIndexMapForOriginalTemplate(interpolatedTokens: InterpolatedAttributeToken[]|
InterpolatedTextToken[]): Map<number, number> {
let offsetMap = new Map<number, number>();
let consumedInOriginalTemplate = 0;
let consumedInInput = 0;
let tokenIndex = 0;
while (consumedInInput < exprStart && tokenIndex < interpolatedTokens.length) {
while (tokenIndex < interpolatedTokens.length) {
const currentToken = interpolatedTokens[tokenIndex];
if (currentToken.type === MlParserTokenType.ENCODED_ENTITY) {
const [decoded, encoded] = currentToken.parts;
Expand All @@ -1335,7 +1337,8 @@ function computeOffsetInOriginalTemplate(
consumedInInput += lengthOfParts;
consumedInOriginalTemplate += lengthOfParts;
}
offsetMap.set(consumedInInput, consumedInOriginalTemplate);
tokenIndex++;
}
return consumedInOriginalTemplate;
return offsetMap;
}

0 comments on commit 7bfc719

Please sign in to comment.