fix(compiler): update unparsable character reference entity error messages (#38319)

Within an angular template, when a character entity is unable to be parsed, previously a generic
unexpected character error was thrown.  This does not properly express the issue that was discovered
as the issue is actually caused by the discovered character making the whole of the entity unparsable.
The compiler will now instead inform via the error message what string was attempted to be parsed
and what it was attempted to be parsed as.

Example, for this template:
```
<p>
  &#x123p
</p>
```
Before this change:
`Unexpected character "p"`

After this change:
`Unable to parse entity "&#x123p" - hexadecimal character reference entities must end with ";"`

Fixes #26067

PR Close #38319
This commit is contained in:
Joey Perrott 2020-07-31 12:26:39 -07:00 committed by Alex Rickabaugh
parent 3a46c2da7c
commit ff9f4de4f1
2 changed files with 26 additions and 7 deletions

View File

@ -138,6 +138,16 @@ function _unknownEntityErrorMsg(entitySrc: string): string {
return `Unknown entity "${entitySrc}" - use the "&#<decimal>;" or "&#x<hex>;" syntax`;
}
function _unparsableEntityErrorMsg(type: CharacterReferenceType, entityStr: string): string {
return `Unable to parse entity "${entityStr}" - ${
type} character reference entities must end with ";"`;
}
enum CharacterReferenceType {
HEX = 'hexadecimal',
DEC = 'decimal',
}
class _ControlFlowError {
constructor(public error: TokenError) {}
}
@ -400,8 +410,13 @@ class _Tokenizer {
const codeStart = this._cursor.clone();
this._attemptCharCodeUntilFn(isDigitEntityEnd);
if (this._cursor.peek() != chars.$SEMICOLON) {
// Advance cursor to include the peeked character in the string provided to the error
// message.
this._cursor.advance();
const entityType = isHex ? CharacterReferenceType.HEX : CharacterReferenceType.DEC;
throw this._createError(
_unexpectedCharacterErrorMsg(this._cursor.peek()), this._cursor.getSpan());
_unparsableEntityErrorMsg(entityType, this._cursor.getChars(start)),
this._cursor.getSpan());
}
const strNum = this._cursor.getChars(codeStart);
this._cursor.advance();

View File

@ -477,12 +477,16 @@ import {ParseLocation, ParseSourceFile, ParseSourceSpan} from '../../src/parse_u
lex.TokenType.TEXT,
'Unknown entity "tbo" - use the "&#<decimal>;" or "&#x<hex>;" syntax', '0:0'
]]);
expect(tokenizeAndHumanizeErrors('&#3sdf;')).toEqual([
[lex.TokenType.TEXT, 'Unexpected character "s"', '0:3']
]);
expect(tokenizeAndHumanizeErrors('&#xasdf;')).toEqual([
[lex.TokenType.TEXT, 'Unexpected character "s"', '0:4']
]);
expect(tokenizeAndHumanizeErrors('&#3sdf;')).toEqual([[
lex.TokenType.TEXT,
'Unable to parse entity "&#3s" - decimal character reference entities must end with ";"',
'0:4'
]]);
expect(tokenizeAndHumanizeErrors('&#xasdf;')).toEqual([[
lex.TokenType.TEXT,
'Unable to parse entity "&#xas" - hexadecimal character reference entities must end with ";"',
'0:5'
]]);
expect(tokenizeAndHumanizeErrors('&#xABC')).toEqual([
[lex.TokenType.TEXT, 'Unexpected character "EOF"', '0:6']