diff --git a/modules/angular2/src/core/change_detection/parser/lexer.ts b/modules/angular2/src/core/change_detection/parser/lexer.ts index aa9cf852b2..460a43c8b6 100644 --- a/modules/angular2/src/core/change_detection/parser/lexer.ts +++ b/modules/angular2/src/core/change_detection/parser/lexer.ts @@ -395,6 +395,18 @@ function isIdentifierStart(code: number): boolean { 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 { return ($a <= code && code <= $z) || ($A <= code && code <= $Z) || ($0 <= code && code <= $9) || (code == $_) || (code == $$); diff --git a/modules/angular2/src/core/change_detection/parser/parser.ts b/modules/angular2/src/core/change_detection/parser/parser.ts index 80fe041176..dbfe8f7f30 100644 --- a/modules/angular2/src/core/change_detection/parser/parser.ts +++ b/modules/angular2/src/core/change_detection/parser/parser.ts @@ -5,6 +5,7 @@ import {ListWrapper} from 'angular2/src/facade/collection'; import { Lexer, EOF, + isIdentifier, Token, $PERIOD, $COLON, @@ -105,15 +106,10 @@ export class Parser { if (isBlank(input)) return null; var prefixSeparatorIndex = input.indexOf(':'); 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); - - // 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); + return new Quote(prefix, uninterpretedExpression, location); } parseTemplateBindings(input: string, location: any): TemplateBinding[] { diff --git a/modules/angular2/test/core/change_detection/parser/parser_spec.ts b/modules/angular2/test/core/change_detection/parser/parser_spec.ts index 06af623177..b13d9c4ca4 100644 --- a/modules/angular2/test/core/change_detection/parser/parser_spec.ts +++ b/modules/angular2/test/core/change_detection/parser/parser_spec.ts @@ -233,6 +233,9 @@ export function main() { 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 refuse prefixes that are not single identifiers', () => {