fix(ivy): validate props and attrs with "on" prefix at runtime (#28054)

Prior to this change we performed prop and attr name validation at compile time, which failed in case a given prop/attr is an input to a Directive (thus should not be a subject to this check). Since Directive matching in Ivy happens at runtime, the corresponding checks are now moved to runtime as well.

PR Close #28054
This commit is contained in:
Andrew Kushnir
2019-01-10 13:34:39 -08:00
parent 857fcfe048
commit 68bdbf0520
5 changed files with 103 additions and 39 deletions

View File

@ -240,7 +240,11 @@ class HtmlAstToIvyAst implements html.Visitor {
literal.push(new t.TextAttribute(
prop.name, prop.expression.source || '', prop.sourceSpan, undefined, i18n));
} else {
const bep = this.bindingParser.createBoundElementProperty(elementName, prop);
// we skip validation here, since we do this check at runtime due to the fact that we need
// to make sure a given prop is not an input of some Directive (thus should not be a subject
// of this check) and Directive matching happens at runtime
const bep = this.bindingParser.createBoundElementProperty(
elementName, prop, /* skipValidation */ true);
bound.push(t.BoundAttribute.fromBoundElementProperty(bep, i18n));
}
});

View File

@ -238,8 +238,9 @@ export class BindingParser {
}
}
createBoundElementProperty(elementSelector: string, boundProp: ParsedProperty):
BoundElementProperty {
createBoundElementProperty(
elementSelector: string, boundProp: ParsedProperty,
skipValidation: boolean = false): BoundElementProperty {
if (boundProp.isAnimation) {
return new BoundElementProperty(
boundProp.name, BindingType.Animation, SecurityContext.NONE, boundProp.expression, null,
@ -252,11 +253,13 @@ export class BindingParser {
const parts = boundProp.name.split(PROPERTY_PARTS_SEPARATOR);
let securityContexts: SecurityContext[] = undefined !;
// Check check for special cases (prefix style, attr, class)
// Check for special cases (prefix style, attr, class)
if (parts.length > 1) {
if (parts[0] == ATTRIBUTE_PREFIX) {
boundPropertyName = parts[1];
this._validatePropertyOrAttributeName(boundPropertyName, boundProp.sourceSpan, true);
if (!skipValidation) {
this._validatePropertyOrAttributeName(boundPropertyName, boundProp.sourceSpan, true);
}
securityContexts = calcPossibleSecurityContexts(
this._schemaRegistry, elementSelector, boundPropertyName, true);
@ -286,7 +289,9 @@ export class BindingParser {
securityContexts = calcPossibleSecurityContexts(
this._schemaRegistry, elementSelector, boundPropertyName, false);
bindingType = BindingType.Property;
this._validatePropertyOrAttributeName(boundPropertyName, boundProp.sourceSpan, false);
if (!skipValidation) {
this._validatePropertyOrAttributeName(boundPropertyName, boundProp.sourceSpan, false);
}
}
return new BoundElementProperty(