fix(TemplateParser): report empty expression (#10391)

fixes #3754
This commit is contained in:
Victor Berchet 2016-08-01 11:24:49 -07:00 committed by GitHub
parent e18626b7a2
commit e73d0511cf
3 changed files with 33 additions and 17 deletions

View File

@ -43,8 +43,8 @@ export class Parser {
input: string, location: any, input: string, location: any,
interpolationConfig: InterpolationConfig = DEFAULT_INTERPOLATION_CONFIG): ASTWithSource { interpolationConfig: InterpolationConfig = DEFAULT_INTERPOLATION_CONFIG): ASTWithSource {
this._checkNoInterpolation(input, location, interpolationConfig); this._checkNoInterpolation(input, location, interpolationConfig);
var tokens = this._lexer.tokenize(this._stripComments(input)); const tokens = this._lexer.tokenize(this._stripComments(input));
var ast = new _ParseAST(input, location, tokens, true, this.errors).parseChain(); const ast = new _ParseAST(input, location, tokens, true, this.errors).parseChain();
return new ASTWithSource(ast, input, location, this.errors); return new ASTWithSource(ast, input, location, this.errors);
} }
@ -155,15 +155,15 @@ export class Parser {
} }
private _stripComments(input: string): string { private _stripComments(input: string): string {
let i = this._commentStart(input); const i = this._commentStart(input);
return isPresent(i) ? input.substring(0, i).trim() : input; return isPresent(i) ? input.substring(0, i).trim() : input;
} }
private _commentStart(input: string): number { private _commentStart(input: string): number {
var outerQuote: number = null; var outerQuote: number = null;
for (var i = 0; i < input.length - 1; i++) { for (let i = 0; i < input.length - 1; i++) {
let char = StringWrapper.charCodeAt(input, i); const char = StringWrapper.charCodeAt(input, i);
let nextChar = StringWrapper.charCodeAt(input, i + 1); const nextChar = StringWrapper.charCodeAt(input, i + 1);
if (char === chars.$SLASH && nextChar == chars.$SLASH && isBlank(outerQuote)) return i; if (char === chars.$SLASH && nextChar == chars.$SLASH && isBlank(outerQuote)) return i;

View File

@ -12,7 +12,7 @@ import {Console, MAX_INTERPOLATION_VALUES} from '../../core_private';
import {ListWrapper, StringMapWrapper, SetWrapper,} from '../facade/collection'; import {ListWrapper, StringMapWrapper, SetWrapper,} from '../facade/collection';
import {RegExpWrapper, isPresent, isBlank} from '../facade/lang'; import {RegExpWrapper, isPresent, isBlank} from '../facade/lang';
import {BaseException} from '../facade/exceptions'; import {BaseException} from '../facade/exceptions';
import {AST, Interpolation, ASTWithSource, TemplateBinding, RecursiveAstVisitor, BindingPipe, ParserError} from '../expression_parser/ast'; import {EmptyExpr, AST, Interpolation, ASTWithSource, TemplateBinding, RecursiveAstVisitor, BindingPipe, ParserError} from '../expression_parser/ast';
import {Parser} from '../expression_parser/parser'; import {Parser} from '../expression_parser/parser';
import {CompileDirectiveMetadata, CompilePipeMetadata, CompileTokenMetadata, removeIdentifierDuplicates,} from '../compile_metadata'; import {CompileDirectiveMetadata, CompilePipeMetadata, CompileTokenMetadata, removeIdentifierDuplicates,} from '../compile_metadata';
import {HtmlParser, ParseTreeResult} from '../html_parser/html_parser'; import {HtmlParser, ParseTreeResult} from '../html_parser/html_parser';
@ -209,7 +209,7 @@ class TemplateParseVisitor implements html.Visitor {
} }
private _reportParserErors(errors: ParserError[], sourceSpan: ParseSourceSpan) { private _reportParserErors(errors: ParserError[], sourceSpan: ParseSourceSpan) {
for (let error of errors) { for (const error of errors) {
this._reportError(error.message, sourceSpan); this._reportError(error.message, sourceSpan);
} }
} }
@ -234,9 +234,16 @@ class TemplateParseVisitor implements html.Visitor {
private _parseAction(value: string, sourceSpan: ParseSourceSpan): ASTWithSource { private _parseAction(value: string, sourceSpan: ParseSourceSpan): ASTWithSource {
const sourceInfo = sourceSpan.start.toString(); const sourceInfo = sourceSpan.start.toString();
try { try {
const ast = this._exprParser.parseAction(value, sourceInfo, this._interpolationConfig); const ast = this._exprParser.parseAction(value, sourceInfo, this._interpolationConfig);
if (ast) this._reportParserErors(ast.errors, sourceSpan); if (ast) {
this._reportParserErors(ast.errors, sourceSpan);
}
if (!ast || ast.ast instanceof EmptyExpr) {
this._reportError(`Empty expressions are not allowed`, sourceSpan);
return this._exprParser.wrapLiteralPrimitive('ERROR', sourceInfo);
}
this._checkPipes(ast, sourceSpan); this._checkPipes(ast, sourceSpan);
return ast; return ast;
} catch (e) { } catch (e) {

View File

@ -328,8 +328,18 @@ export function main() {
describe('events', () => { describe('events', () => {
it('should parse bound events with a target', () => { it('should parse bound events with a target', () => {
expect(humanizeTplAst(parse('<div (window:event)="v">', [ expect(humanizeTplAst(parse('<div (window:event)="v">', []))).toEqual([
]))).toEqual([[ElementAst, 'div'], [BoundEventAst, 'event', 'window', 'v']]); [ElementAst, 'div'],
[BoundEventAst, 'event', 'window', 'v'],
]);
});
it('should report an error on empty expression', () => {
expect(() => parse('<div (event)="">', []))
.toThrowError(/Empty expressions are not allowed/);
expect(() => parse('<div (event)=" ">', []))
.toThrowError(/Empty expressions are not allowed/);
}); });
it('should parse bound events via (...) and not report them as attributes', () => { it('should parse bound events via (...) and not report them as attributes', () => {
@ -519,10 +529,10 @@ export function main() {
}); });
describe('providers', () => { describe('providers', () => {
var nextProviderId: any /** TODO #9100 */; var nextProviderId: number;
function createToken(value: string): CompileTokenMetadata { function createToken(value: string): CompileTokenMetadata {
var token: any /** TODO #9100 */; let token: CompileTokenMetadata;
if (value.startsWith('type:')) { if (value.startsWith('type:')) {
token = new CompileTokenMetadata({ token = new CompileTokenMetadata({
identifier: identifier:
@ -555,8 +565,8 @@ export function main() {
} }
function createProvider( function createProvider(
token: string, {multi = false, deps = /*@ts2dart_const*/[]}: token: string, {multi = false, deps = []}: {multi?: boolean, deps?: string[]} = {}):
{multi?: boolean, deps?: string[]} = {}): CompileProviderMetadata { CompileProviderMetadata {
return new CompileProviderMetadata({ return new CompileProviderMetadata({
token: createToken(token), token: createToken(token),
multi: multi, multi: multi,
@ -566,8 +576,7 @@ export function main() {
} }
function createDir( function createDir(
selector: string, {providers = null, viewProviders = null, deps = /*@ts2dart_const*/[], selector: string, {providers = null, viewProviders = null, deps = [], queries = []}: {
queries = /*@ts2dart_const*/[]}: {
providers?: CompileProviderMetadata[], providers?: CompileProviderMetadata[],
viewProviders?: CompileProviderMetadata[], viewProviders?: CompileProviderMetadata[],
deps?: string[], deps?: string[],