fix(ivy): process property bindings in i18n blocks similar to non-i18n bindings (#28969)

Prior to this change i18n block bindings were converted to Expressions right away (once we first access them), when in non-i18n cases we processed them differently: the actual conversion happens at instructions generation. Because of this discrepancy, the output for bindings in i18n blocks was generated incorrectly (with invalid indicies in pipeBindN fns and invalid references to non-existent local variables). Now the bindings processing is unified and i18nExp instructions should contain right bind expressions.

PR Close #28969
This commit is contained in:
Andrew Kushnir
2019-02-25 15:26:10 -08:00
committed by Ben Lesh
parent 34bdebcdd2
commit 40833ba54b
5 changed files with 71 additions and 25 deletions

View File

@ -6,6 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {AST} from '../../../expression_parser/ast';
import * as i18n from '../../../i18n/i18n_ast';
import * as o from '../../../output/output_ast';
@ -40,7 +41,7 @@ function setupRegistry() {
*/
export class I18nContext {
public readonly id: number;
public bindings = new Set<o.Expression>();
public bindings = new Set<AST>();
public placeholders = new Map<string, any[]>();
public isEmitted: boolean = false;
@ -75,7 +76,7 @@ export class I18nContext {
}
// public API to accumulate i18n-related content
appendBinding(binding: o.Expression) { this.bindings.add(binding); }
appendBinding(binding: AST) { this.bindings.add(binding); }
appendIcu(name: string, ref: o.Expression) {
updatePlaceholderMap(this._registry.icus, name, ref);
}

View File

@ -329,12 +329,9 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
}
i18nAppendBindings(expressions: AST[]) {
if (!this.i18n || !expressions.length) return;
const implicit = o.variable(CONTEXT_NAME);
expressions.forEach(expression => {
const binding = this.convertExpressionBinding(implicit, expression);
this.i18n !.appendBinding(binding);
});
if (expressions.length > 0) {
expressions.forEach(expression => this.i18n !.appendBinding(expression));
}
}
i18nBindProps(props: {[key: string]: t.Text | t.BoundText}): {[key: string]: o.Expression} {
@ -452,7 +449,11 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
// setup accumulated bindings
const {index, bindings} = this.i18n;
if (bindings.size) {
bindings.forEach(binding => this.updateInstruction(span, R3.i18nExp, [binding]));
bindings.forEach(binding => {
this.updateInstruction(
span, R3.i18nExp,
() => [this.convertPropertyBinding(o.variable(CONTEXT_NAME), binding)]);
});
this.updateInstruction(span, R3.i18nApply, [o.literal(index)]);
}
if (!selfClosing) {