@@ -801,7 +801,7 @@ function asMessage(i18nMeta: i18n.I18nMeta|null|undefined): i18n.Message|null { |
801 | 801 | return null; |
802 | 802 | } |
803 | 803 | if (!(i18nMeta instanceof i18n.Message)) { |
804 | | - throw Error(`Unhandled i18n metadata type for binding: ${i18nMeta.constructor.name}`); |
| 804 | + throw Error(`Expected i18n meta to be a Message, but got: ${i18nMeta.constructor.name}`); |
805 | 805 | } |
806 | 806 | return i18nMeta; |
807 | 807 | } |
@@ -867,27 +867,26 @@ function ingestTemplateBindings( |
867 | 867 | if (attr instanceof t.TextAttribute) { |
868 | 868 | bindings.push(createTemplateBinding( |
869 | 869 | unit, op.xref, e.BindingType.Attribute, attr.name, attr.value, null, SecurityContext.NONE, |
870 | | - true, true, templateKind, asMessage(attr.i18n), attr.sourceSpan)); |
| 870 | + true, templateKind, asMessage(attr.i18n), attr.sourceSpan)); |
871 | 871 | } else { |
872 | 872 | bindings.push(createTemplateBinding( |
873 | 873 | unit, op.xref, attr.type, attr.name, astOf(attr.value), attr.unit, attr.securityContext, |
874 | | - false, true, templateKind, asMessage(attr.i18n), attr.sourceSpan)); |
| 874 | + true, templateKind, asMessage(attr.i18n), attr.sourceSpan)); |
875 | 875 | } |
876 | 876 | } |
877 | 877 |
|
878 | 878 | for (const attr of template.attributes) { |
879 | 879 | // Attribute literal bindings, such as `attr.foo="bar"`. |
880 | 880 | bindings.push(createTemplateBinding( |
881 | 881 | unit, op.xref, e.BindingType.Attribute, attr.name, attr.value, null, SecurityContext.NONE, |
882 | | - true, false, templateKind, asMessage(attr.i18n), attr.sourceSpan)); |
| 882 | + false, templateKind, asMessage(attr.i18n), attr.sourceSpan)); |
883 | 883 | } |
884 | 884 |
|
885 | 885 | for (const input of template.inputs) { |
886 | 886 | // Dynamic bindings (both attribute and property bindings). |
887 | 887 | bindings.push(createTemplateBinding( |
888 | 888 | unit, op.xref, input.type, input.name, astOf(input.value), input.unit, |
889 | | - input.securityContext, false, false, templateKind, asMessage(input.i18n), |
890 | | - input.sourceSpan)); |
| 889 | + input.securityContext, false, templateKind, asMessage(input.i18n), input.sourceSpan)); |
891 | 890 | } |
892 | 891 |
|
893 | 892 | unit.create.push(bindings.filter( |
@@ -905,7 +904,8 @@ function ingestTemplateBindings( |
905 | 904 | makeListenerHandlerOps(unit, output.handler, output.handlerSpan), output.phase, false, |
906 | 905 | output.sourceSpan)); |
907 | 906 | } |
908 | | - if (templateKind === ir.TemplateKind.Structural && output.type === e.ParsedEventType.Regular) { |
| 907 | + if (templateKind === ir.TemplateKind.Structural && |
| 908 | + output.type !== e.ParsedEventType.Animation) { |
909 | 909 | // Animation bindings are excluded from the structural template's const array. |
910 | 910 | unit.create.push(ir.createExtractedAttributeOp( |
911 | 911 | op.xref, ir.BindingKind.Property, output.name, null, null, null)); |
@@ -938,24 +938,22 @@ function ingestTemplateBindings( |
938 | 938 | * string literal if the parser considered it a text binding. |
939 | 939 | * @param unit If the binding has a unit (e.g. `px` for style bindings), then this is the unit. |
940 | 940 | * @param securityContext The security context of the binding. |
941 | | - * @param isTextBinding Whether the binding is a text binding according to the parser (e.g. `<div |
942 | | - * literal="foo">`). Even if this is false, the binding still might be an extractable constant |
943 | | - * expression (see the later attribute extraction phase). |
944 | 941 | * @param isStructuralTemplateAttribute Whether this binding actually applies to the structural |
945 | 942 | * ng-template. For example, an `ngFor` would actually apply to the structural template. (Most |
946 | 943 | * bindings on structural elements target the inner element, not the template.) |
947 | 944 | * @param templateKind Whether this is an explicit `ng-template` or an implicit template created by |
948 | | - * a structural directive. |
| 945 | + * a structural directive. This should never be a block template. |
949 | 946 | * @param i18nMessage The i18n metadata for the binding, if any. |
950 | 947 | * @param sourceSpan The source span of the binding. |
951 | 948 | * @returns An IR binding op, or null if the binding should be skipped. |
952 | 949 | */ |
953 | 950 | function createTemplateBinding( |
954 | 951 | view: ViewCompilationUnit, xref: ir.XrefId, type: e.BindingType, name: string, |
955 | 952 | value: e.AST|string, unit: string|null, securityContext: SecurityContext, |
956 | | - isTextBinding: boolean, isStructuralTemplateAttribute: boolean, |
957 | | - templateKind: ir.TemplateKind|null, i18nMessage: i18n.Message|null, |
958 | | - sourceSpan: ParseSourceSpan): ir.BindingOp|ir.ExtractedAttributeOp|null { |
| 953 | + isStructuralTemplateAttribute: boolean, templateKind: ir.TemplateKind|null, |
| 954 | + i18nMessage: i18n.Message|null, sourceSpan: ParseSourceSpan): ir.BindingOp| |
| 955 | + ir.ExtractedAttributeOp|null { |
| 956 | + const isTextBinding = typeof value === 'string'; |
959 | 957 | // If this is a structural template, then several kinds of bindings should not result in an |
960 | 958 | // update instruction. |
961 | 959 | if (templateKind === ir.TemplateKind.Structural) { |
|