fix(compiler): detect pipes in ICUs in template binder (#38810)
Recent work on compiler internals in #38539 led to an unexpected failure, where a pipe used exclusively inside of an ICU would no longer be emitted into the compilation output. This caused runtime errors due to missing pipes. The issue occurred because the change in #38539 would determine the set of used pipes up-front, independent from the template compilation using the `R3TargetBinder`. However, `R3TargetBinder` did not consider expressions within ICUs, so any pipe usages within those expressions would not be detected. This fix unblocks #38539 and also concerns upcoming linker work, given that prelink compilations would not go through full template compilation but only `R3TargetBinder`. PR Close #38810
This commit is contained in:
parent
66129f8ea6
commit
15207e3c9c
|
@ -434,7 +434,10 @@ class TemplateBinder extends RecursiveAstVisitor implements Visitor {
|
|||
visitText(text: Text) {}
|
||||
visitContent(content: Content) {}
|
||||
visitTextAttribute(attribute: TextAttribute) {}
|
||||
visitIcu(icu: Icu): void {}
|
||||
visitIcu(icu: Icu): void {
|
||||
Object.keys(icu.vars).forEach(key => icu.vars[key].visit(this));
|
||||
Object.keys(icu.placeholders).forEach(key => icu.placeholders[key].visit(this));
|
||||
}
|
||||
|
||||
// The remaining visitors are concerned with processing AST expressions within template bindings
|
||||
|
||||
|
|
|
@ -194,4 +194,38 @@ describe('t2 binding', () => {
|
|||
expect(consumer).toEqual(el);
|
||||
});
|
||||
});
|
||||
|
||||
describe('used pipes', () => {
|
||||
it('should record pipes used in interpolations', () => {
|
||||
const template = parseTemplate('{{value|date}}', '', {});
|
||||
const binder = new R3TargetBinder(makeSelectorMatcher());
|
||||
const res = binder.bind({template: template.nodes});
|
||||
expect(res.getUsedPipes()).toEqual(['date']);
|
||||
});
|
||||
|
||||
it('should record pipes used in bound attributes', () => {
|
||||
const template = parseTemplate('<person [age]="age|number"></person>', '', {});
|
||||
const binder = new R3TargetBinder(makeSelectorMatcher());
|
||||
const res = binder.bind({template: template.nodes});
|
||||
expect(res.getUsedPipes()).toEqual(['number']);
|
||||
});
|
||||
|
||||
it('should record pipes used in bound template attributes', () => {
|
||||
const template = parseTemplate('<ng-template [ngIf]="obs|async"></ng-template>', '', {});
|
||||
const binder = new R3TargetBinder(makeSelectorMatcher());
|
||||
const res = binder.bind({template: template.nodes});
|
||||
expect(res.getUsedPipes()).toEqual(['async']);
|
||||
});
|
||||
|
||||
it('should record pipes used in ICUs', () => {
|
||||
const template = parseTemplate(
|
||||
`<span i18n>{count|number, plural,
|
||||
=1 { {{value|date}} }
|
||||
}</span>`,
|
||||
'', {});
|
||||
const binder = new R3TargetBinder(makeSelectorMatcher());
|
||||
const res = binder.bind({template: template.nodes});
|
||||
expect(res.getUsedPipes()).toEqual(['number', 'date']);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue