fix(parser): do not crash on untokenizable quote prefixes

Closes #5486
This commit is contained in:
Yegor Jbanov 2015-11-25 15:28:42 -08:00 committed by Yegor
parent 1bec4f6c61
commit b90de66535
3 changed files with 19 additions and 8 deletions

View File

@ -395,6 +395,18 @@ function isIdentifierStart(code: number): boolean {
return ($a <= code && code <= $z) || ($A <= code && code <= $Z) || (code == $_) || (code == $$); return ($a <= code && code <= $z) || ($A <= code && code <= $Z) || (code == $_) || (code == $$);
} }
export function isIdentifier(input: string): boolean {
if (input.length == 0) return false;
var scanner = new _Scanner(input);
if (!isIdentifierStart(scanner.peek)) return false;
scanner.advance();
while (scanner.peek !== $EOF) {
if (!isIdentifierPart(scanner.peek)) return false;
scanner.advance();
}
return true;
}
function isIdentifierPart(code: number): boolean { function isIdentifierPart(code: number): boolean {
return ($a <= code && code <= $z) || ($A <= code && code <= $Z) || ($0 <= code && code <= $9) || return ($a <= code && code <= $z) || ($A <= code && code <= $Z) || ($0 <= code && code <= $9) ||
(code == $_) || (code == $$); (code == $_) || (code == $$);

View File

@ -5,6 +5,7 @@ import {ListWrapper} from 'angular2/src/facade/collection';
import { import {
Lexer, Lexer,
EOF, EOF,
isIdentifier,
Token, Token,
$PERIOD, $PERIOD,
$COLON, $COLON,
@ -105,15 +106,10 @@ export class Parser {
if (isBlank(input)) return null; if (isBlank(input)) return null;
var prefixSeparatorIndex = input.indexOf(':'); var prefixSeparatorIndex = input.indexOf(':');
if (prefixSeparatorIndex == -1) return null; if (prefixSeparatorIndex == -1) return null;
var prefix = input.substring(0, prefixSeparatorIndex); var prefix = input.substring(0, prefixSeparatorIndex).trim();
if (!isIdentifier(prefix)) return null;
var uninterpretedExpression = input.substring(prefixSeparatorIndex + 1); var uninterpretedExpression = input.substring(prefixSeparatorIndex + 1);
return new Quote(prefix, uninterpretedExpression, location);
// while we do not interpret the expression, we do interpret the prefix
var prefixTokens = this._lexer.tokenize(prefix);
// quote prefix must be a single legal identifier
if (prefixTokens.length != 1 || !prefixTokens[0].isIdentifier()) return null;
return new Quote(prefixTokens[0].strValue, uninterpretedExpression, location);
} }
parseTemplateBindings(input: string, location: any): TemplateBinding[] { parseTemplateBindings(input: string, location: any): TemplateBinding[] {

View File

@ -233,6 +233,9 @@ export function main() {
it('should parse quoted expressions', () => { checkBinding('a:b', 'a:b'); }); it('should parse quoted expressions', () => { checkBinding('a:b', 'a:b'); });
it('should not crash when prefix part is not tokenizable',
() => { checkBinding('"a:b"', '"a:b"'); });
it('should ignore whitespace around quote prefix', () => { checkBinding(' a :b', 'a:b'); }); it('should ignore whitespace around quote prefix', () => { checkBinding(' a :b', 'a:b'); });
it('should refuse prefixes that are not single identifiers', () => { it('should refuse prefixes that are not single identifiers', () => {