fix(compiler): handle invalid host bindings and events (#11101)

This commit is contained in:
Pawel Kozlowski 2016-08-26 19:29:53 +02:00 committed by Victor Berchet
parent 0a053a4cd5
commit f25c97671a
2 changed files with 41 additions and 5 deletions

View File

@ -13,7 +13,7 @@ import {CompileDirectiveMetadata, CompilePipeMetadata, CompileTokenMetadata, rem
import {AST, ASTWithSource, BindingPipe, EmptyExpr, Interpolation, ParserError, RecursiveAstVisitor, TemplateBinding} from '../expression_parser/ast'; import {AST, ASTWithSource, BindingPipe, EmptyExpr, Interpolation, ParserError, RecursiveAstVisitor, TemplateBinding} from '../expression_parser/ast';
import {Parser} from '../expression_parser/parser'; import {Parser} from '../expression_parser/parser';
import {ListWrapper, SetWrapper, StringMapWrapper} from '../facade/collection'; import {ListWrapper, SetWrapper, StringMapWrapper} from '../facade/collection';
import {isBlank, isPresent} from '../facade/lang'; import {isBlank, isPresent, isString} from '../facade/lang';
import {HtmlParser} from '../i18n/html_parser'; import {HtmlParser} from '../i18n/html_parser';
import {Identifiers, identifierToken} from '../identifiers'; import {Identifiers, identifierToken} from '../identifiers';
import * as html from '../ml_parser/ast'; import * as html from '../ml_parser/ast';
@ -746,9 +746,15 @@ class TemplateParseVisitor implements html.Visitor {
targetPropertyAsts: BoundElementPropertyAst[]) { targetPropertyAsts: BoundElementPropertyAst[]) {
if (isPresent(hostProps)) { if (isPresent(hostProps)) {
StringMapWrapper.forEach(hostProps, (expression: string, propName: string) => { StringMapWrapper.forEach(hostProps, (expression: string, propName: string) => {
const exprAst = this._parseBinding(expression, sourceSpan); if (isString(expression)) {
targetPropertyAsts.push( const exprAst = this._parseBinding(expression, sourceSpan);
this._createElementPropertyAst(elementName, propName, exprAst, sourceSpan)); targetPropertyAsts.push(
this._createElementPropertyAst(elementName, propName, exprAst, sourceSpan));
} else {
this._reportError(
`Value of the host property binding "${propName}" needs to be a string representing an expression but got "${expression}" (${typeof expression})`,
sourceSpan);
}
}); });
} }
} }
@ -758,7 +764,13 @@ class TemplateParseVisitor implements html.Visitor {
targetEventAsts: BoundEventAst[]) { targetEventAsts: BoundEventAst[]) {
if (isPresent(hostListeners)) { if (isPresent(hostListeners)) {
StringMapWrapper.forEach(hostListeners, (expression: string, propName: string) => { StringMapWrapper.forEach(hostListeners, (expression: string, propName: string) => {
this._parseEvent(propName, expression, sourceSpan, [], targetEventAsts); if (isString(expression)) {
this._parseEvent(propName, expression, sourceSpan, [], targetEventAsts);
} else {
this._reportError(
`Value of the host listener "${propName}" needs to be a string representing an expression but got "${expression}" (${typeof expression})`,
sourceSpan);
}
}); });
} }
} }

View File

@ -313,6 +313,30 @@ Can't bind to 'invalidProp' since it isn't a known property of 'my-component'.
expect(console.warnings.length).toEqual(0); expect(console.warnings.length).toEqual(0);
}); });
it('should throw descriptive error when a host binding is not a string expression', () => {
var dirA = CompileDirectiveMetadata.create({
selector: 'broken',
type: new CompileTypeMetadata({moduleUrl: someModuleUrl, name: 'DirA'}),
host: {'[class.foo]': null}
});
expect(() => { parse('<broken></broken>', [dirA]); })
.toThrowError(
`Template parse errors:\nValue of the host property binding "class.foo" needs to be a string representing an expression but got "null" (object) ("[ERROR ->]<broken></broken>"): TestComp@0:0, Directive DirA`);
});
it('should throw descriptive error when a host event is not a string expression', () => {
var dirA = CompileDirectiveMetadata.create({
selector: 'broken',
type: new CompileTypeMetadata({moduleUrl: someModuleUrl, name: 'DirA'}),
host: {'(click)': null}
});
expect(() => { parse('<broken></broken>', [dirA]); })
.toThrowError(
`Template parse errors:\nValue of the host listener "click" needs to be a string representing an expression but got "null" (object) ("[ERROR ->]<broken></broken>"): TestComp@0:0, Directive DirA`);
});
it('should not issue a warning when an animation property is bound without an expression', it('should not issue a warning when an animation property is bound without an expression',
() => { () => {
humanizeTplAst(parse('<div @something>', [])); humanizeTplAst(parse('<div @something>', []));